Skip to content

Commit 673090e

Browse files
committed
Separate AnonymousCreateParameter and ReportElidedInPath.
1 parent b5caa5a commit 673090e

File tree

1 file changed

+115
-87
lines changed

1 file changed

+115
-87
lines changed

compiler/rustc_resolve/src/late.rs

+115-87
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,12 @@ enum LifetimeRibKind {
222222
/// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
223223
AnonConst,
224224

225-
/// For **Modern** cases, create a new anonymous region parameter
226-
/// and reference that.
227-
///
228-
/// For **Dyn Bound** cases, pass responsibility to
229-
/// `resolve_lifetime` code.
230-
///
231-
/// For **Deprecated** cases, report an error.
225+
/// Create a new anonymous region parameter and reference that.
232226
AnonymousCreateParameter(NodeId),
233227

228+
/// Give a hard error when generic lifetime arguments are elided.
229+
ReportElidedInPath,
230+
234231
/// Give a hard error when either `&` or `'_` is written. Used to
235232
/// rule out things like `where T: Foo<'_>`. Does not imply an
236233
/// error on default object bounds (e.g., `Box<dyn Foo>`).
@@ -746,8 +743,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
746743
this.with_lifetime_rib(
747744
LifetimeRibKind::AnonymousCreateParameter(fn_id),
748745
|this| {
749-
// Add each argument to the rib.
750-
this.resolve_params(&declaration.inputs)
746+
this.with_lifetime_rib(LifetimeRibKind::ReportElidedInPath, |this| {
747+
// Add each argument to the rib.
748+
this.resolve_params(&declaration.inputs)
749+
});
751750
},
752751
);
753752

@@ -1301,7 +1300,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13011300
let rib = &mut self.lifetime_ribs[i];
13021301
match rib.kind {
13031302
LifetimeRibKind::AnonymousCreateParameter(item_node_id) => {
1304-
self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id);
1303+
let region =
1304+
self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id);
1305+
self.record_lifetime_res(lifetime.id, region);
13051306
return;
13061307
}
13071308
LifetimeRibKind::AnonymousReportError => {
@@ -1358,7 +1359,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13581359
}
13591360

13601361
#[tracing::instrument(level = "debug", skip(self))]
1361-
fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, item_node_id: NodeId) {
1362+
fn create_fresh_lifetime(
1363+
&mut self,
1364+
id: NodeId,
1365+
ident: Ident,
1366+
item_node_id: NodeId,
1367+
) -> LifetimeRes {
13621368
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
13631369
debug!(?ident.span);
13641370
let item_def_id = self.r.local_def_id(item_node_id);
@@ -1373,12 +1379,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13731379
debug!(?def_id);
13741380

13751381
let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id };
1376-
self.record_lifetime_res(id, region);
13771382
self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push((
13781383
ident,
13791384
def_node_id,
13801385
region,
13811386
));
1387+
region
13821388
}
13831389

13841390
#[tracing::instrument(level = "debug", skip(self))]
@@ -1391,7 +1397,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
13911397
path_span: Span,
13921398
) {
13931399
let proj_start = path.len() - partial_res.unresolved_segments();
1394-
for (i, segment) in path.iter().enumerate() {
1400+
'segment: for (i, segment) in path.iter().enumerate() {
13951401
if segment.has_lifetime_args {
13961402
continue;
13971403
}
@@ -1428,16 +1434,69 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14281434
| PathSource::Struct
14291435
| PathSource::TupleStruct(..) => false,
14301436
};
1431-
let mut res = LifetimeRes::Error;
1437+
1438+
let node_ids = self.r.next_node_ids(expected_lifetimes);
1439+
self.record_lifetime_res(
1440+
segment_id,
1441+
LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
1442+
);
1443+
1444+
if !missing {
1445+
for i in 0..expected_lifetimes {
1446+
let id = node_ids.start.plus(i);
1447+
self.record_lifetime_res(
1448+
id,
1449+
LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true },
1450+
);
1451+
}
1452+
continue;
1453+
}
1454+
1455+
let elided_lifetime_span = if segment.has_generic_args {
1456+
// If there are brackets, but not generic arguments, then use the opening bracket
1457+
segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
1458+
} else {
1459+
// If there are no brackets, use the identifier span.
1460+
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1461+
// originating from macros, since the segment's span might be from a macro arg.
1462+
segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
1463+
};
1464+
14321465
for rib in self.lifetime_ribs.iter().rev() {
14331466
match rib.kind {
1434-
// In create-parameter mode we error here because we don't want to support
1435-
// deprecated impl elision in new features like impl elision and `async fn`,
1436-
// both of which work using the `CreateParameter` mode:
1437-
//
1438-
// impl Foo for std::cell::Ref<u32> // note lack of '_
1439-
// async fn foo(_: std::cell::Ref<u32>) { ... }
1440-
LifetimeRibKind::AnonymousCreateParameter(_) => {
1467+
// We error here because we don't want to support deprecated impl elision in
1468+
// new features like impl elision and `async fn`,
1469+
LifetimeRibKind::ReportElidedInPath => {
1470+
let sess = self.r.session;
1471+
let mut err = rustc_errors::struct_span_err!(
1472+
sess,
1473+
path_span,
1474+
E0726,
1475+
"implicit elided lifetime not allowed here"
1476+
);
1477+
rustc_errors::add_elided_lifetime_in_path_suggestion(
1478+
sess.source_map(),
1479+
&mut err,
1480+
expected_lifetimes,
1481+
path_span,
1482+
!segment.has_generic_args,
1483+
elided_lifetime_span,
1484+
);
1485+
err.note("assuming a `'static` lifetime...");
1486+
err.emit();
1487+
for i in 0..expected_lifetimes {
1488+
let id = node_ids.start.plus(i);
1489+
self.record_lifetime_res(id, LifetimeRes::Error);
1490+
}
1491+
continue 'segment;
1492+
}
1493+
LifetimeRibKind::AnonymousCreateParameter(binder) => {
1494+
let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span);
1495+
for i in 0..expected_lifetimes {
1496+
let id = node_ids.start.plus(i);
1497+
let res = self.create_fresh_lifetime(id, ident, binder);
1498+
self.record_lifetime_res(id, res);
1499+
}
14411500
break;
14421501
}
14431502
// `PassThrough` is the normal case.
@@ -1447,75 +1506,40 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14471506
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
14481507
// later, at which point a suitable error will be emitted.
14491508
LifetimeRibKind::AnonymousPassThrough(binder, _) => {
1450-
res = LifetimeRes::Anonymous { binder, elided: true };
1509+
let res = LifetimeRes::Anonymous { binder, elided: true };
1510+
for i in 0..expected_lifetimes {
1511+
let id = node_ids.start.plus(i);
1512+
self.record_lifetime_res(id, res);
1513+
}
14511514
break;
14521515
}
14531516
LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
14541517
// FIXME(cjgillot) This resolution is wrong, but this does not matter
14551518
// since these cases are erroneous anyway. Lifetime resolution should
14561519
// emit a "missing lifetime specifier" diagnostic.
1457-
res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
1520+
let res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
1521+
for i in 0..expected_lifetimes {
1522+
let id = node_ids.start.plus(i);
1523+
self.record_lifetime_res(id, res);
1524+
}
14581525
break;
14591526
}
14601527
_ => {}
14611528
}
14621529
}
14631530

1464-
let node_ids = self.r.next_node_ids(expected_lifetimes);
1465-
self.record_lifetime_res(
1531+
self.r.lint_buffer.buffer_lint_with_diagnostic(
1532+
lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
14661533
segment_id,
1467-
LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
1468-
);
1469-
for i in 0..expected_lifetimes {
1470-
let id = node_ids.start.plus(i);
1471-
self.record_lifetime_res(id, res);
1472-
}
1473-
1474-
if !missing {
1475-
continue;
1476-
}
1477-
1478-
let elided_lifetime_span = if segment.has_generic_args {
1479-
// If there are brackets, but not generic arguments, then use the opening bracket
1480-
segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
1481-
} else {
1482-
// If there are no brackets, use the identifier span.
1483-
// HACK: we use find_ancestor_inside to properly suggest elided spans in paths
1484-
// originating from macros, since the segment's span might be from a macro arg.
1485-
segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
1486-
};
1487-
if let LifetimeRes::Error = res {
1488-
let sess = self.r.session;
1489-
let mut err = rustc_errors::struct_span_err!(
1490-
sess,
1491-
path_span,
1492-
E0726,
1493-
"implicit elided lifetime not allowed here"
1494-
);
1495-
rustc_errors::add_elided_lifetime_in_path_suggestion(
1496-
sess.source_map(),
1497-
&mut err,
1534+
elided_lifetime_span,
1535+
"hidden lifetime parameters in types are deprecated",
1536+
lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
14981537
expected_lifetimes,
14991538
path_span,
15001539
!segment.has_generic_args,
15011540
elided_lifetime_span,
1502-
);
1503-
err.note("assuming a `'static` lifetime...");
1504-
err.emit();
1505-
} else {
1506-
self.r.lint_buffer.buffer_lint_with_diagnostic(
1507-
lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
1508-
segment_id,
1509-
elided_lifetime_span,
1510-
"hidden lifetime parameters in types are deprecated",
1511-
lint::BuiltinLintDiagnostics::ElidedLifetimesInPaths(
1512-
expected_lifetimes,
1513-
path_span,
1514-
!segment.has_generic_args,
1515-
elided_lifetime_span,
1516-
),
1517-
);
1518-
}
1541+
),
1542+
);
15191543
}
15201544
}
15211545

@@ -2072,12 +2096,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
20722096
let mut new_id = None;
20732097
if let Some(trait_ref) = opt_trait_ref {
20742098
let path: Vec<_> = Segment::from_path(&trait_ref.path);
2075-
let res = self.smart_resolve_path_fragment(
2076-
None,
2077-
&path,
2078-
PathSource::Trait(AliasPossibility::No),
2079-
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
2080-
);
2099+
let res = self.with_lifetime_rib(LifetimeRibKind::ReportElidedInPath, |this| {
2100+
this.smart_resolve_path_fragment(
2101+
None,
2102+
&path,
2103+
PathSource::Trait(AliasPossibility::No),
2104+
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
2105+
)
2106+
});
20812107
if let Some(def_id) = res.base_res().opt_def_id() {
20822108
new_id = Some(def_id);
20832109
new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
@@ -2130,14 +2156,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
21302156
let res =
21312157
Res::SelfTy { trait_: trait_id, alias_to: Some((item_def_id, false)) };
21322158
this.with_self_rib(res, |this| {
2133-
if let Some(trait_ref) = opt_trait_reference.as_ref() {
2134-
// Resolve type arguments in the trait path.
2135-
visit::walk_trait_ref(this, trait_ref);
2136-
}
2137-
// Resolve the self type.
2138-
this.visit_ty(self_type);
2139-
// Resolve the generic parameters.
2140-
this.visit_generics(generics);
2159+
this.with_lifetime_rib(LifetimeRibKind::ReportElidedInPath, |this| {
2160+
if let Some(trait_ref) = opt_trait_reference.as_ref() {
2161+
// Resolve type arguments in the trait path.
2162+
visit::walk_trait_ref(this, trait_ref);
2163+
}
2164+
// Resolve the self type.
2165+
this.visit_ty(self_type);
2166+
// Resolve the generic parameters.
2167+
this.visit_generics(generics);
2168+
});
21412169

21422170
// Resolve the items within the impl.
21432171
this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id,false),

0 commit comments

Comments
 (0)