Skip to content

Commit 1eed627

Browse files
authored
Rollup merge of rust-lang#64151 - estebank:binding-error, r=varkor
On obligation errors point at the unfulfilled binding when possible CC rust-lang#42855, rust-lang#64130, rust-lang#64135.
2 parents a44881d + eac2b02 commit 1eed627

File tree

170 files changed

+712
-605
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

170 files changed

+712
-605
lines changed

src/etc/generate-deriving-span-tests.py

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))
1515

1616
TEMPLATE = """\
17+
// ignore-musl
18+
// ^ due to stderr output differences
1719
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
1820
1921
{error_deriving}

src/librustc/hir/lowering.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1893,10 +1893,13 @@ impl<'a> LoweringContext<'a> {
18931893
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
18941894
// Do not suggest going from `Trait()` to `Trait<>`
18951895
if data.inputs.len() > 0 {
1896+
let split = snippet.find('(').unwrap();
1897+
let trait_name = &snippet[0..split];
1898+
let args = &snippet[split + 1 .. snippet.len() - 1];
18961899
err.span_suggestion(
18971900
data.span,
18981901
"use angle brackets instead",
1899-
format!("<{}>", &snippet[1..snippet.len() - 1]),
1902+
format!("{}<{}>", trait_name, args),
19001903
Applicability::MaybeIncorrect,
19011904
);
19021905
}

src/librustc/hir/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -2750,3 +2750,15 @@ pub enum Node<'hir> {
27502750

27512751
Crate,
27522752
}
2753+
2754+
impl Node<'_> {
2755+
pub fn ident(&self) -> Option<Ident> {
2756+
match self {
2757+
Node::TraitItem(TraitItem { ident, .. }) |
2758+
Node::ImplItem(ImplItem { ident, .. }) |
2759+
Node::ForeignItem(ForeignItem { ident, .. }) |
2760+
Node::Item(Item { ident, .. }) => Some(*ident),
2761+
_ => None,
2762+
}
2763+
}
2764+
}

src/librustc/traits/error_reporting.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ use syntax::symbol::{sym, kw};
4040
use syntax_pos::{DUMMY_SP, Span, ExpnKind};
4141

4242
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
43-
pub fn report_fulfillment_errors(&self,
44-
errors: &[FulfillmentError<'tcx>],
45-
body_id: Option<hir::BodyId>,
46-
fallback_has_occurred: bool) {
43+
pub fn report_fulfillment_errors(
44+
&self,
45+
errors: &[FulfillmentError<'tcx>],
46+
body_id: Option<hir::BodyId>,
47+
fallback_has_occurred: bool,
48+
) {
4749
#[derive(Debug)]
4850
struct ErrorDescriptor<'tcx> {
4951
predicate: ty::Predicate<'tcx>,
@@ -1623,6 +1625,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16231625
err.note(&msg);
16241626
}
16251627
}
1628+
ObligationCauseCode::BindingObligation(item_def_id, span) => {
1629+
let item_name = tcx.def_path_str(item_def_id);
1630+
let msg = format!("required by this bound in `{}`", item_name);
1631+
if let Some(ident) = tcx.opt_item_name(item_def_id) {
1632+
err.span_label(ident.span, "");
1633+
}
1634+
if span != DUMMY_SP {
1635+
err.span_label(span, &msg);
1636+
} else {
1637+
err.note(&msg);
1638+
}
1639+
}
16261640
ObligationCauseCode::ObjectCastObligation(object_ty) => {
16271641
err.note(&format!("required for the cast to the object type `{}`",
16281642
self.ty_to_string(object_ty)));

src/librustc/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ pub enum ObligationCauseCode<'tcx> {
176176
/// also implement all supertraits of `X`.
177177
ItemObligation(DefId),
178178

179+
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
180+
BindingObligation(DefId, Span),
181+
179182
/// A type like `&'a T` is WF only if `T: 'a`.
180183
ReferenceOutlivesReferent(Ty<'tcx>),
181184

src/librustc/traits/structural_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
472472
super::TupleElem => Some(super::TupleElem),
473473
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
474474
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
475+
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
475476
super::ReferenceOutlivesReferent(ty) => {
476477
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
477478
}

src/librustc/ty/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2791,6 +2791,10 @@ impl<'tcx> TyCtxt<'tcx> {
27912791
})
27922792
}
27932793

2794+
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
2795+
self.hir().as_local_hir_id(def_id).and_then(|hir_id| self.hir().get(hir_id).ident())
2796+
}
2797+
27942798
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
27952799
let is_associated_item = if let Some(hir_id) = self.hir().as_local_hir_id(def_id) {
27962800
match self.hir().get(hir_id) {

src/librustc_typeck/check/mod.rs

+38-14
Original file line numberDiff line numberDiff line change
@@ -2579,16 +2579,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25792579

25802580
/// As `instantiate_type_scheme`, but for the bounds found in a
25812581
/// generic type scheme.
2582-
fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: SubstsRef<'tcx>)
2583-
-> ty::InstantiatedPredicates<'tcx> {
2582+
fn instantiate_bounds(
2583+
&self,
2584+
span: Span,
2585+
def_id: DefId,
2586+
substs: SubstsRef<'tcx>,
2587+
) -> (ty::InstantiatedPredicates<'tcx>, Vec<Span>) {
25842588
let bounds = self.tcx.predicates_of(def_id);
2589+
let spans: Vec<Span> = bounds.predicates.iter().map(|(_, span)| *span).collect();
25852590
let result = bounds.instantiate(self.tcx, substs);
25862591
let result = self.normalize_associated_types_in(span, &result);
2587-
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
2592+
debug!(
2593+
"instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}",
25882594
bounds,
25892595
substs,
2590-
result);
2591-
result
2596+
result,
2597+
spans,
2598+
);
2599+
(result, spans)
25922600
}
25932601

25942602
/// Replaces the opaque types from the given value with type variables,
@@ -3151,8 +3159,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31513159

31523160
// All the input types from the fn signature must outlive the call
31533161
// so as to validate implied bounds.
3154-
for &fn_input_ty in fn_inputs {
3155-
self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
3162+
for (fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) {
3163+
self.register_wf_obligation(fn_input_ty, arg_expr.span, traits::MiscObligation);
31563164
}
31573165

31583166
let expected_arg_count = fn_inputs.len();
@@ -3513,7 +3521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
35133521
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
35143522

35153523
// Check bounds on type arguments used in the path.
3516-
let bounds = self.instantiate_bounds(path_span, did, substs);
3524+
let (bounds, _) = self.instantiate_bounds(path_span, did, substs);
35173525
let cause = traits::ObligationCause::new(path_span, self.body_id,
35183526
traits::ItemObligation(did));
35193527
self.add_obligations_for_parameters(cause, &bounds);
@@ -4634,12 +4642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46344642
// First, store the "user substs" for later.
46354643
self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
46364644

4637-
// Add all the obligations that are required, substituting and
4638-
// normalized appropriately.
4639-
let bounds = self.instantiate_bounds(span, def_id, &substs);
4640-
self.add_obligations_for_parameters(
4641-
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
4642-
&bounds);
4645+
self.add_required_obligations(span, def_id, &substs);
46434646

46444647
// Substitute the values for the type parameters into the type of
46454648
// the referenced item.
@@ -4676,6 +4679,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46764679
(ty_substituted, res)
46774680
}
46784681

4682+
/// Add all the obligations that are required, substituting and normalized appropriately.
4683+
fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) {
4684+
let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs);
4685+
4686+
for (i, mut obligation) in traits::predicates_for_generics(
4687+
traits::ObligationCause::new(
4688+
span,
4689+
self.body_id,
4690+
traits::ItemObligation(def_id),
4691+
),
4692+
self.param_env,
4693+
&bounds,
4694+
).into_iter().enumerate() {
4695+
// This makes the error point at the bound, but we want to point at the argument
4696+
if let Some(span) = spans.get(i) {
4697+
obligation.cause.code = traits::BindingObligation(def_id, *span);
4698+
}
4699+
self.register_predicate(obligation);
4700+
}
4701+
}
4702+
46794703
fn check_rustc_args_require_const(&self,
46804704
def_id: DefId,
46814705
hir_id: hir::HirId,

src/libsyntax/parse/parser/path.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,11 @@ impl<'a> Parser<'a> {
129129
self.parse_path(style)
130130
}
131131

132-
crate fn parse_path_segments(&mut self,
133-
segments: &mut Vec<PathSegment>,
134-
style: PathStyle)
135-
-> PResult<'a, ()> {
132+
crate fn parse_path_segments(
133+
&mut self,
134+
segments: &mut Vec<PathSegment>,
135+
style: PathStyle,
136+
) -> PResult<'a, ()> {
136137
loop {
137138
let segment = self.parse_path_segment(style)?;
138139
if style == PathStyle::Expr {
@@ -201,7 +202,7 @@ impl<'a> Parser<'a> {
201202
} else {
202203
// `(T, U) -> R`
203204
let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
204-
let span = lo.to(self.prev_span);
205+
let span = ident.span.to(self.prev_span);
205206
let output = if self.eat(&token::RArrow) {
206207
Some(self.parse_ty_common(false, false, false)?)
207208
} else {

0 commit comments

Comments
 (0)