Skip to content

Commit 066a0ae

Browse files
committed
Auto merge of #43343 - petrochenkov:methlife3, r=estebank
Add an extra note to `late_bound_lifetime_arguments` error/lint Fixes #42868 (comment)
2 parents f0b07ca + 18d9701 commit 066a0ae

7 files changed

+140
-24
lines changed

Diff for: src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ pub struct Generics {
719719
pub type_param_to_index: BTreeMap<DefIndex, u32>,
720720

721721
pub has_self: bool,
722-
pub has_late_bound_regions: bool,
722+
pub has_late_bound_regions: Option<Span>,
723723
}
724724

725725
impl Generics {

Diff for: src/librustc_typeck/check/mod.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ use syntax::feature_gate::{GateIssue, emit_feature_err};
121121
use syntax::ptr::P;
122122
use syntax::symbol::{Symbol, InternedString, keywords};
123123
use syntax::util::lev_distance::find_best_match_for_name;
124-
use syntax_pos::{self, BytePos, Span};
124+
use syntax_pos::{self, BytePos, Span, MultiSpan};
125125

126126
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
127127
use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -4689,20 +4689,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
46894689

46904690
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
46914691
let has_late_bound_lifetime_defs =
4692-
segment.map_or(false, |(_, generics)| generics.has_late_bound_regions);
4693-
if has_late_bound_lifetime_defs && !lifetimes.is_empty() {
4692+
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
4693+
if let (Some(span_late), false) = (has_late_bound_lifetime_defs, lifetimes.is_empty()) {
46944694
// Report this as a lint only if no error was reported previously.
4695+
let primary_msg = "cannot specify lifetime arguments explicitly \
4696+
if late bound lifetime parameters are present";
4697+
let note_msg = "the late bound lifetime parameter is introduced here";
46954698
if !is_method_call && (lifetimes.len() > lifetime_defs.len() ||
46964699
lifetimes.len() < required_len && !infer_lifetimes) {
4697-
self.tcx.sess.span_err(lifetimes[0].span,
4698-
"cannot specify lifetime arguments explicitly \
4699-
if late bound lifetime parameters are present");
4700+
let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
4701+
err.span_note(span_late, note_msg);
4702+
err.emit();
47004703
*segment = None;
47014704
} else {
4705+
let mut multispan = MultiSpan::from_span(lifetimes[0].span);
4706+
multispan.push_span_label(span_late, note_msg.to_string());
47024707
self.tcx.sess.add_lint(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
4703-
lifetimes[0].id, lifetimes[0].span,
4704-
format!("cannot specify lifetime arguments explicitly \
4705-
if late bound lifetime parameters are present"));
4708+
lifetimes[0].id, multispan, primary_msg.to_string());
47064709
}
47074710
return;
47084711
}

Diff for: src/librustc_typeck/collect.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -774,11 +774,11 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
774774

775775
fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
776776
node: hir_map::Node<'tcx>)
777-
-> bool {
777+
-> Option<Span> {
778778
struct LateBoundRegionsDetector<'a, 'tcx: 'a> {
779779
tcx: TyCtxt<'a, 'tcx, 'tcx>,
780780
binder_depth: u32,
781-
has_late_bound_regions: bool,
781+
has_late_bound_regions: Option<Span>,
782782
}
783783

784784
impl<'a, 'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'a, 'tcx> {
@@ -787,7 +787,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
787787
}
788788

789789
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
790-
if self.has_late_bound_regions { return }
790+
if self.has_late_bound_regions.is_some() { return }
791791
match ty.node {
792792
hir::TyBareFn(..) => {
793793
self.binder_depth += 1;
@@ -801,35 +801,35 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
801801
fn visit_poly_trait_ref(&mut self,
802802
tr: &'tcx hir::PolyTraitRef,
803803
m: hir::TraitBoundModifier) {
804-
if self.has_late_bound_regions { return }
804+
if self.has_late_bound_regions.is_some() { return }
805805
self.binder_depth += 1;
806806
intravisit::walk_poly_trait_ref(self, tr, m);
807807
self.binder_depth -= 1;
808808
}
809809

810810
fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
811-
if self.has_late_bound_regions { return }
811+
if self.has_late_bound_regions.is_some() { return }
812812

813813
match self.tcx.named_region_map.defs.get(&lt.id).cloned() {
814814
Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
815815
Some(rl::Region::LateBound(debruijn, _)) |
816816
Some(rl::Region::LateBoundAnon(debruijn, _))
817817
if debruijn.depth < self.binder_depth => {}
818-
_ => self.has_late_bound_regions = true,
818+
_ => self.has_late_bound_regions = Some(lt.span),
819819
}
820820
}
821821
}
822822

823823
fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
824824
generics: &'tcx hir::Generics,
825825
decl: &'tcx hir::FnDecl)
826-
-> bool {
826+
-> Option<Span> {
827827
let mut visitor = LateBoundRegionsDetector {
828-
tcx, binder_depth: 1, has_late_bound_regions: false
828+
tcx, binder_depth: 1, has_late_bound_regions: None
829829
};
830830
for lifetime in &generics.lifetimes {
831831
if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) {
832-
return true;
832+
return Some(lifetime.lifetime.span);
833833
}
834834
}
835835
visitor.visit_fn_decl(decl);
@@ -840,24 +840,24 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
840840
hir_map::NodeTraitItem(item) => match item.node {
841841
hir::TraitItemKind::Method(ref sig, _) =>
842842
has_late_bound_regions(tcx, &sig.generics, &sig.decl),
843-
_ => false,
843+
_ => None,
844844
},
845845
hir_map::NodeImplItem(item) => match item.node {
846846
hir::ImplItemKind::Method(ref sig, _) =>
847847
has_late_bound_regions(tcx, &sig.generics, &sig.decl),
848-
_ => false,
848+
_ => None,
849849
},
850850
hir_map::NodeForeignItem(item) => match item.node {
851851
hir::ForeignItemFn(ref fn_decl, _, ref generics) =>
852852
has_late_bound_regions(tcx, generics, fn_decl),
853-
_ => false,
853+
_ => None,
854854
},
855855
hir_map::NodeItem(item) => match item.node {
856856
hir::ItemFn(ref fn_decl, .., ref generics, _) =>
857857
has_late_bound_regions(tcx, generics, fn_decl),
858-
_ => false,
858+
_ => None,
859859
},
860-
_ => false
860+
_ => None
861861
}
862862
}
863863

Diff for: src/test/ui/method-call-lifetime-args-lint.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![deny(late_bound_lifetime_arguments)]
12+
#![allow(unused)]
13+
14+
struct S;
15+
16+
impl S {
17+
fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
18+
fn late_implicit(self, _: &u8, _: &u8) {}
19+
}
20+
21+
fn method_call() {
22+
S.late::<'static>(&0, &0);
23+
//~^ ERROR cannot specify lifetime arguments explicitly
24+
//~| WARN this was previously accepted
25+
26+
S.late_implicit::<'static>(&0, &0);
27+
//~^ ERROR cannot specify lifetime arguments explicitly
28+
//~| WARN this was previously accepted
29+
}
30+
31+
fn main() {}

Diff for: src/test/ui/method-call-lifetime-args-lint.stderr

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
2+
--> $DIR/method-call-lifetime-args-lint.rs:22:14
3+
|
4+
17 | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
5+
| -- the late bound lifetime parameter is introduced here
6+
...
7+
22 | S.late::<'static>(&0, &0);
8+
| ^^^^^^^
9+
|
10+
note: lint level defined here
11+
--> $DIR/method-call-lifetime-args-lint.rs:11:9
12+
|
13+
11 | #![deny(late_bound_lifetime_arguments)]
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
16+
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
17+
18+
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
19+
--> $DIR/method-call-lifetime-args-lint.rs:26:23
20+
|
21+
18 | fn late_implicit(self, _: &u8, _: &u8) {}
22+
| - the late bound lifetime parameter is introduced here
23+
...
24+
26 | S.late_implicit::<'static>(&0, &0);
25+
| ^^^^^^^
26+
|
27+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
28+
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
29+
30+
error: aborting due to 2 previous errors
31+

Diff for: src/test/ui/method-call-lifetime-args.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct S;
12+
13+
impl S {
14+
fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
15+
fn late_implicit(self, _: &u8, _: &u8) {}
16+
}
17+
18+
fn ufcs() {
19+
S::late::<'static>(S, &0, &0);
20+
//~^ ERROR cannot specify lifetime arguments explicitly
21+
S::late_implicit::<'static>(S, &0, &0);
22+
//~^ ERROR cannot specify lifetime arguments explicitly
23+
}
24+
25+
fn main() {}

Diff for: src/test/ui/method-call-lifetime-args.stderr

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
2+
--> $DIR/method-call-lifetime-args.rs:19:15
3+
|
4+
19 | S::late::<'static>(S, &0, &0);
5+
| ^^^^^^^
6+
|
7+
note: the late bound lifetime parameter is introduced here
8+
--> $DIR/method-call-lifetime-args.rs:14:13
9+
|
10+
14 | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
11+
| ^^
12+
13+
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
14+
--> $DIR/method-call-lifetime-args.rs:21:24
15+
|
16+
21 | S::late_implicit::<'static>(S, &0, &0);
17+
| ^^^^^^^
18+
|
19+
note: the late bound lifetime parameter is introduced here
20+
--> $DIR/method-call-lifetime-args.rs:15:31
21+
|
22+
15 | fn late_implicit(self, _: &u8, _: &u8) {}
23+
| ^
24+
25+
error: aborting due to 2 previous errors
26+

0 commit comments

Comments
 (0)