Skip to content

Commit 9a9bb44

Browse files
bors[bot]philberty
andauthored
Merge #1184
1184: Fix bad name resolution on path with generic segments r=philberty a=philberty This fix breaks down into two commits the first commit fixes the issue directly then the second one fixes the regression that was introduced in the first. The TLDR for this patch set is that when we resolve the path here: module::transmute The name-resolver wronly added the specified generic arguments into the canonical path meaning that the root segment could not be name-resolved such that during type resolution we iterate and apply the generic arguments appropriately to the root segment. In fixing this it introduced a regression exposing a few more complex issues with inference variables but for a more complete explanation about that please read the commit message from ea38a59 Fixes #1173 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
2 parents 60f7f99 + ea38a59 commit 9a9bb44

File tree

9 files changed

+96
-107
lines changed

9 files changed

+96
-107
lines changed

gcc/rust/hir/tree/rust-hir-path.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ class PathPattern : public Pattern
262262

263263
std::vector<PathExprSegment> &get_segments () { return segments; }
264264

265+
const std::vector<PathExprSegment> &get_segments () const { return segments; }
266+
265267
PathExprSegment &get_root_seg () { return segments.at (0); }
266268

267269
PathExprSegment get_final_segment () const { return segments.back (); }

gcc/rust/resolve/rust-ast-resolve-type.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,8 @@ class ResolvePathSegmentToCanonicalPath
169169
return CanonicalPath::create_empty ();
170170
}
171171

172-
std::string generics
173-
= ResolveTypeToCanonicalPath::canonicalize_generic_args (
174-
seg.get_generic_args ());
175-
176172
return CanonicalPath::new_seg (seg.get_node_id (),
177-
seg.get_ident_segment ().as_string ()
178-
+ "::" + generics);
173+
seg.get_ident_segment ().as_string ());
179174
}
180175
};
181176

gcc/rust/typecheck/rust-hir-type-check-expr.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,13 +221,6 @@ class TypeCheckExpr : public TypeCheckBase
221221

222222
infered
223223
= TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
224-
if (infered == nullptr)
225-
{
226-
rust_error_at (expr.get_locus (), "failed to lookup type to CallExpr");
227-
return;
228-
}
229-
230-
infered->set_ref (expr.get_mappings ().get_hirid ());
231224
}
232225

233226
void visit (HIR::MethodCallExpr &expr) override
@@ -1076,7 +1069,6 @@ class TypeCheckExpr : public TypeCheckBase
10761069
: TypeCheckBase (), infered (nullptr), inside_loop (inside_loop)
10771070
{}
10781071

1079-
// Beware: currently returns Tyty::ErrorType or nullptr in case of error.
10801072
TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr,
10811073
size_t *offset,
10821074
NodeId *root_resolved_node_id);

gcc/rust/typecheck/rust-hir-type-check-path.cc

Lines changed: 25 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -138,27 +138,17 @@ void
138138
TypeCheckExpr::visit (HIR::PathInExpression &expr)
139139
{
140140
NodeId resolved_node_id = UNKNOWN_NODEID;
141-
142141
size_t offset = -1;
143142
TyTy::BaseType *tyseg = resolve_root_path (expr, &offset, &resolved_node_id);
144-
rust_assert (tyseg != nullptr);
145-
146143
if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
147144
return;
148145

149-
if (expr.get_num_segments () == 1)
150-
{
151-
Location locus = expr.get_segments ().back ().get_locus ();
152-
153-
bool is_big_self
154-
= expr.get_segments ().front ().get_segment ().as_string ().compare (
155-
"Self")
156-
== 0;
157-
if (!is_big_self && tyseg->needs_generic_substitutions ())
158-
{
159-
tyseg = SubstMapper::InferSubst (tyseg, locus);
160-
}
146+
if (tyseg->needs_generic_substitutions ())
147+
tyseg = SubstMapper::InferSubst (tyseg, expr.get_locus ());
161148

149+
bool fully_resolved = offset == expr.get_segments ().size ();
150+
if (fully_resolved)
151+
{
162152
infered = tyseg;
163153
return;
164154
}
@@ -171,14 +161,11 @@ TyTy::BaseType *
171161
TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
172162
NodeId *root_resolved_node_id)
173163
{
174-
TyTy::BaseType *root_tyty = nullptr;
175164
*offset = 0;
176165
for (size_t i = 0; i < expr.get_num_segments (); i++)
177166
{
178167
HIR::PathExprSegment &seg = expr.get_segments ().at (i);
179-
180168
bool have_more_segments = (expr.get_num_segments () - 1 != i);
181-
bool is_root = *offset == 0 || root_tyty == nullptr;
182169
NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
183170

184171
// then lookup the reference_node_id
@@ -205,40 +192,30 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
205192
// ref_node_id is the NodeId that the segments refers to.
206193
if (ref_node_id == UNKNOWN_NODEID)
207194
{
208-
if (is_root)
209-
{
210-
rust_error_at (seg.get_locus (),
211-
"failed to type resolve root segment");
212-
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
213-
}
214-
return root_tyty;
195+
rust_error_at (seg.get_locus (),
196+
"failed to type resolve root segment");
197+
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
215198
}
216199

217200
// node back to HIR
218201
HirId ref;
219202
if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
220203
ref_node_id, &ref))
221204
{
222-
if (is_root)
223-
{
224-
rust_error_at (seg.get_locus (), "456 reverse lookup failure");
225-
rust_debug_loc (
226-
seg.get_locus (),
227-
"failure with [%s] mappings [%s] ref_node_id [%u]",
228-
seg.as_string ().c_str (),
229-
seg.get_mappings ().as_string ().c_str (), ref_node_id);
205+
rust_error_at (seg.get_locus (), "456 reverse lookup failure");
206+
rust_debug_loc (seg.get_locus (),
207+
"failure with [%s] mappings [%s] ref_node_id [%u]",
208+
seg.as_string ().c_str (),
209+
seg.get_mappings ().as_string ().c_str (),
210+
ref_node_id);
230211

231-
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
232-
}
233-
234-
return root_tyty;
212+
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
235213
}
236214

237215
auto seg_is_module
238216
= (nullptr
239217
!= mappings->lookup_module (expr.get_mappings ().get_crate_num (),
240218
ref));
241-
242219
if (seg_is_module)
243220
{
244221
// A::B::C::this_is_a_module::D::E::F
@@ -261,33 +238,8 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
261238
TyTy::BaseType *lookup = nullptr;
262239
if (!context->lookup_type (ref, &lookup))
263240
{
264-
if (is_root)
265-
{
266-
rust_error_at (seg.get_locus (),
267-
"failed to resolve root segment");
268-
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
269-
}
270-
return root_tyty;
271-
}
272-
273-
// if we have a previous segment type
274-
if (root_tyty != nullptr)
275-
{
276-
// if this next segment needs substitution we must apply the
277-
// previous type arguments
278-
//
279-
// such as: GenericStruct::<_>::new(123, 456)
280-
if (lookup->needs_generic_substitutions ())
281-
{
282-
if (!root_tyty->needs_generic_substitutions ())
283-
{
284-
auto used_args_in_prev_segment
285-
= GetUsedSubstArgs::From (root_tyty);
286-
lookup
287-
= SubstMapperInternal::Resolve (lookup,
288-
used_args_in_prev_segment);
289-
}
290-
}
241+
rust_error_at (seg.get_locus (), "failed to resolve root segment");
242+
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
291243
}
292244

293245
// turbo-fish segment path::<ty>
@@ -300,16 +252,16 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
300252
lookup->as_string ().c_str ());
301253
return new TyTy::ErrorType (lookup->get_ref ());
302254
}
303-
lookup = SubstMapper::Resolve (lookup, expr.get_locus (),
255+
lookup = SubstMapper::Resolve (lookup, seg.get_locus (),
304256
&seg.get_generic_args ());
305257
}
306258

307259
*root_resolved_node_id = ref_node_id;
308260
*offset = *offset + 1;
309-
root_tyty = lookup;
261+
return lookup;
310262
}
311263

312-
return root_tyty;
264+
return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
313265
}
314266

315267
void
@@ -424,19 +376,11 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
424376
bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
425377
rust_assert (ok);
426378

427-
if (prev_segment->needs_generic_substitutions ())
428-
{
429-
if (!impl_block_ty->needs_generic_substitutions ())
430-
{
431-
prev_segment = impl_block_ty;
432-
}
433-
else
434-
{
435-
HIR::PathExprSegment &pseg = segments.at (i - 1);
436-
Location locus = pseg.get_locus ();
437-
prev_segment = SubstMapper::InferSubst (prev_segment, locus);
438-
}
439-
}
379+
if (impl_block_ty->needs_generic_substitutions ())
380+
impl_block_ty
381+
= SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
382+
383+
prev_segment = prev_segment->unify (impl_block_ty);
440384
}
441385

442386
if (tyseg->needs_generic_substitutions ())

gcc/rust/typecheck/rust-hir-type-check.cc

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,11 @@ TypeResolution::Resolve (HIR::Crate &crate)
5454

5555
// default inference variables if possible
5656
context->iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool {
57-
if (ty->get_kind () == TyTy::TypeKind::ERROR)
58-
{
59-
rust_error_at (mappings->lookup_location (id),
60-
"failure in type resolution for %u", id);
61-
return false;
62-
}
63-
6457
// nothing to do
6558
if (ty->get_kind () != TyTy::TypeKind::INFER)
6659
return true;
6760

68-
TyTy::InferType *infer_var = (TyTy::InferType *) ty;
61+
TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
6962
TyTy::BaseType *default_type;
7063
bool ok = infer_var->default_type (&default_type);
7164
if (!ok)

gcc/rust/typecheck/rust-tyty-rules.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ class BaseRules : public TyVisitor
8989
for (auto ref : other->get_combined_refs ())
9090
resolved->append_reference (ref);
9191

92+
other->append_reference (resolved->get_ref ());
93+
other->append_reference (get_base ()->get_ref ());
94+
get_base ()->append_reference (resolved->get_ref ());
95+
get_base ()->append_reference (other->get_ref ());
96+
9297
bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
9398
bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
9499
bool results_is_non_general_infer_var

gcc/rust/typecheck/rust-tyty.cc

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ TyVar::get_implicit_infer_var (Location locus)
263263
infer);
264264
mappings->insert_location (mappings->get_current_crate (), infer->get_ref (),
265265
locus);
266+
266267
return TyVar (infer->get_ref ());
267268
}
268269

@@ -341,8 +342,34 @@ InferType::cast (BaseType *other)
341342
BaseType *
342343
InferType::clone () const
343344
{
344-
return new InferType (get_ref (), get_ty_ref (), get_infer_kind (),
345-
get_ident ().locus, get_combined_refs ());
345+
// clones for inference variables are special in that they _must_ exist within
346+
// the type check context and we must ensure we don't loose the chain
347+
// otherwise we will end up in the missing type annotations case
348+
//
349+
// This means we cannot simply take over the same reference we must generate a
350+
// new ref just like the get_implicit_infer_var code then we can setup the
351+
// chain of references accordingly to ensure we don't loose the ability to
352+
// update the inference variables when we solve the type
353+
354+
auto mappings = Analysis::Mappings::get ();
355+
auto context = Resolver::TypeCheckContext::get ();
356+
357+
InferType *clone
358+
= new InferType (mappings->get_next_hir_id (), get_infer_kind (),
359+
get_ident ().locus, get_combined_refs ());
360+
361+
context->insert_type (Analysis::NodeMapping (mappings->get_current_crate (),
362+
UNKNOWN_NODEID,
363+
clone->get_ref (),
364+
UNKNOWN_LOCAL_DEFID),
365+
clone);
366+
mappings->insert_location (mappings->get_current_crate (), clone->get_ref (),
367+
mappings->lookup_location (get_ref ()));
368+
369+
// setup the chain to reference this
370+
clone->append_reference (get_ref ());
371+
372+
return clone;
346373
}
347374

348375
bool

gcc/rust/typecheck/rust-tyty.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,12 +955,23 @@ class SubstitutionRef
955955
BaseType *infer_substitions (Location locus)
956956
{
957957
std::vector<SubstitutionArg> args;
958+
std::map<std::string, BaseType *> argument_mappings;
958959
for (auto &p : get_substs ())
959960
{
960961
if (p.needs_substitution ())
961962
{
962-
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
963-
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
963+
const std::string &symbol = p.get_param_ty ()->get_symbol ();
964+
auto it = argument_mappings.find (symbol);
965+
if (it == argument_mappings.end ())
966+
{
967+
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
968+
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
969+
argument_mappings[symbol] = infer_var.get_tyty ();
970+
}
971+
else
972+
{
973+
args.push_back (SubstitutionArg (&p, it->second));
974+
}
964975
}
965976
else
966977
{
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// { dg-additional-options "-w" }
2+
mod mem {
3+
extern "rust-intrinsic" {
4+
fn transmute<U, V>(_: U) -> V;
5+
}
6+
}
7+
8+
pub trait Hasher {
9+
fn write(&mut self, bytes: &[u8]);
10+
fn write_u16(&mut self, i: u16) {
11+
self.write(&mem::transmute::<_, [u8; 2]>(i))
12+
}
13+
}
14+
15+
pub struct SipHasher;
16+
17+
impl Hasher for SipHasher {
18+
#[inline]
19+
fn write(&mut self, msg: &[u8]) {}
20+
}

0 commit comments

Comments
 (0)