Skip to content

Commit

Permalink
Auto merge of rust-lang#115821 - obeis:hir-analysis-migrate-diagnosti…
Browse files Browse the repository at this point in the history
…cs-5, r=compiler-errors

Migrate `rustc_hir_analysis` to session diagnostic [Part 5]

Finishing `coherence/builtin.rs` file
  • Loading branch information
bors committed Sep 29, 2023
2 parents 7b4d9e1 + 77e205a commit 958c2b8
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 125 deletions.
25 changes: 25 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr
hir_analysis_closure_implicit_hrtb = implicit types in closure signatures are forbidden when `for<...>` is present
.label = `for<...>` is here
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
.note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
.coercions_note = currently, {$number} fields need coercions: {$coercions}
.label = requires multiple coercions
hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}`
hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found
hir_analysis_const_bound_for_non_const_trait =
~const can only be applied to `#[const_trait]` traits
Expand All @@ -61,6 +72,15 @@ hir_analysis_copy_impl_on_type_with_dtor =
the trait `Copy` cannot be implemented for this type; the type has a destructor
.label = `Copy` not allowed on types with destructors
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
.coercions_note = currently, {$number} fields need coercions: {$coercions}
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment, and nothing else
.note = extra field `{$name}` of type `{$ty}` is not allowed
hir_analysis_drop_impl_negative = negative `Drop` impls are not supported
hir_analysis_drop_impl_on_wrong_item =
Expand Down Expand Up @@ -232,6 +252,8 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
.label = not allowed in type signatures
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
hir_analysis_return_type_notation_conflicting_bound =
ambiguous associated function `{$assoc_name}` for `{$ty_name}`
.note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
Expand Down Expand Up @@ -299,6 +321,9 @@ hir_analysis_too_large_static = extern static is too large for the current archi
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
.suggestion = remove this annotation
hir_analysis_trait_cannot_impl_for_ty = the trait `{$trait_name}` cannot be implemented for this type
.label = this field does not implement `{$trait_name}`
hir_analysis_trait_object_declared_with_no_traits =
at least one trait is required for an object type
.alias_span = this alias does not contain a trait
Expand Down
200 changes: 78 additions & 122 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
//! Check properties that are required by built-in traits and set
//! up data structures required by type-checking/codegen.

use crate::errors::{
ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem,
};
use crate::errors;

use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
Expand Down Expand Up @@ -65,7 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {

let impl_ = tcx.hir().expect_item(impl_did).expect_impl();

tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span });
tcx.sess.emit_err(errors::DropImplOnWrongItem { span: impl_.self_ty.span });
}

fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
Expand All @@ -91,10 +90,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span);
}
Err(CopyImplementationError::NotAnAdt) => {
tcx.sess.emit_err(CopyImplOnNonAdt { span });
tcx.sess.emit_err(errors::CopyImplOnNonAdt { span });
}
Err(CopyImplementationError::HasDestructor) => {
tcx.sess.emit_err(CopyImplOnTypeWithDtor { span });
tcx.sess.emit_err(errors::CopyImplOnTypeWithDtor { span });
}
}
}
Expand All @@ -117,7 +116,7 @@ fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId)
infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span);
}
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span });
tcx.sess.emit_err(errors::ConstParamTyImplOnNonAdt { span });
}
}
}
Expand Down Expand Up @@ -152,8 +151,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef

let param_env = tcx.param_env(impl_did);

let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);

let infcx = tcx.infer_ctxt().build();
let cause = ObligationCause::misc(span, impl_did);

Expand All @@ -176,22 +173,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
let source_path = tcx.def_path_str(def_a.did());
let target_path = tcx.def_path_str(def_b.did());

create_err(&format!(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures with the same \
definition; expected `{source_path}`, found `{target_path}`",
))
.emit();
tcx.sess.emit_err(errors::DispatchFromDynCoercion {
span,
trait_name: "DispatchFromDyn",
note: true,
source_path,
target_path,
});

return;
}

if def_a.repr().c() || def_a.repr().packed() {
create_err(
"structs implementing `DispatchFromDyn` may not have \
`#[repr(packed)]` or `#[repr(C)]`",
)
.emit();
tcx.sess.emit_err(errors::DispatchFromDynRepr { span });
}

let fields = &def_a.non_enum_variant().fields;
Expand All @@ -213,16 +207,11 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, ty_a, ty_b)
{
if ok.obligations.is_empty() {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
for structs containing the field being coerced, \
ZST fields with 1 byte alignment, and nothing else",
)
.note(format!(
"extra field `{}` of type `{}` is not allowed",
field.name, ty_a,
))
.emit();
tcx.sess.emit_err(errors::DispatchFromDynZST {
span,
name: field.name,
ty: ty_a,
});

return false;
}
Expand All @@ -233,36 +222,29 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
.collect::<Vec<_>>();

if coerced_fields.is_empty() {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures with a single field \
being coerced, none found",
)
.emit();
tcx.sess.emit_err(errors::DispatchFromDynSingle {
span,
trait_name: "DispatchFromDyn",
note: true,
});
} else if coerced_fields.len() > 1 {
create_err("implementing the `DispatchFromDyn` trait requires multiple coercions")
.note(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures with a single field \
being coerced",
)
.note(format!(
"currently, {} fields need coercions: {}",
coerced_fields.len(),
coerced_fields
.iter()
.map(|field| {
format!(
"`{}` (`{}` to `{}`)",
field.name,
field.ty(tcx, args_a),
field.ty(tcx, args_b),
)
})
.collect::<Vec<_>>()
.join(", ")
))
.emit();
tcx.sess.emit_err(errors::DispatchFromDynMulti {
span,
coercions_note: true,
number: coerced_fields.len(),
coercions: coerced_fields
.iter()
.map(|field| {
format!(
"`{}` (`{}` to `{}`)",
field.name,
field.ty(tcx, args_a),
field.ty(tcx, args_b),
)
})
.collect::<Vec<_>>()
.join(", "),
});
} else {
let ocx = ObligationCtxt::new(&infcx);
for field in coerced_fields {
Expand All @@ -288,11 +270,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
}
_ => {
create_err(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures",
)
.emit();
tcx.sess.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" });
}
}
}
Expand Down Expand Up @@ -359,17 +337,13 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
if def_a != def_b {
let source_path = tcx.def_path_str(def_a.did());
let target_path = tcx.def_path_str(def_b.did());
struct_span_err!(
tcx.sess,
tcx.sess.emit_err(errors::DispatchFromDynSame {
span,
E0377,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with the same \
definition; expected `{}`, found `{}`",
trait_name: "CoerceUnsized",
note: true,
source_path,
target_path
)
.emit();
target_path,
});
return err_info;
}

Expand Down Expand Up @@ -445,15 +419,11 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
.collect::<Vec<_>>();

if diff_fields.is_empty() {
struct_span_err!(
tcx.sess,
tcx.sess.emit_err(errors::CoerceUnsizedOneField {
span,
E0374,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures with one field \
being coerced, none found"
)
.emit();
trait_name: "CoerceUnsized",
note: true,
});
return err_info;
} else if diff_fields.len() > 1 {
let item = tcx.hir().expect_item(impl_did);
Expand All @@ -463,29 +433,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
tcx.def_span(impl_did)
};

struct_span_err!(
tcx.sess,
tcx.sess.emit_err(errors::CoerceUnsizedMulti {
span,
E0375,
"implementing the trait \
`CoerceUnsized` requires multiple \
coercions"
)
.note(
"`CoerceUnsized` may only be implemented for \
a coercion between structures with one field being coerced",
)
.note(format!(
"currently, {} fields need coercions: {}",
diff_fields.len(),
diff_fields
coercions_note: true,
number: diff_fields.len(),
coercions: diff_fields
.iter()
.map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) })
.map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
.collect::<Vec<_>>()
.join(", ")
))
.span_label(span, "requires multiple coercions")
.emit();
.join(", "),
});

return err_info;
}

Expand All @@ -495,14 +453,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
}

_ => {
struct_span_err!(
tcx.sess,
span,
E0376,
"the trait `CoerceUnsized` may only be implemented \
for a coercion between structures"
)
.emit();
tcx.sess.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" });
return err_info;
}
};
Expand Down Expand Up @@ -540,28 +491,22 @@ fn infringing_fields_error(

let trait_name = tcx.def_path_str(trait_did);

let mut err = struct_span_err!(
tcx.sess,
impl_span,
E0204,
"the trait `{trait_name}` cannot be implemented for this type"
);

// We'll try to suggest constraining type parameters to fulfill the requirements of
// their `Copy` implementation.
let mut errors: BTreeMap<_, Vec<_>> = Default::default();
let mut bounds = vec![];

let mut seen_tys = FxHashSet::default();

let mut label_spans = Vec::new();

for (field, ty, reason) in fields {
// Only report an error once per type.
if !seen_tys.insert(ty) {
continue;
}

let field_span = tcx.def_span(field.did);
err.span_label(field_span, format!("this field does not implement `{trait_name}`"));
label_spans.push(tcx.def_span(field.did));

match reason {
InfringingFieldsReason::Fulfill(fulfillment_errors) => {
Expand Down Expand Up @@ -625,13 +570,24 @@ fn infringing_fields_error(
}
}
}
let mut notes = Vec::new();
for ((ty, error_predicate), spans) in errors {
let span: MultiSpan = spans.into();
err.span_note(
notes.push(errors::ImplForTyRequires {
span,
format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
);
error_predicate,
trait_name: trait_name.clone(),
ty,
});
}

let mut err = tcx.sess.create_err(errors::TraitCannotImplForTy {
span: impl_span,
trait_name,
label_spans,
notes,
});

suggest_constraining_type_params(
tcx,
tcx.hir().get_generics(impl_did).expect("impls always have generics"),
Expand Down
Loading

0 comments on commit 958c2b8

Please sign in to comment.