Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
err.subdiagnostic(CaptureReasonLabel::BorrowContent {
var_span: var_span.shrink_to_hi(),
});
}
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, tcx).ty;
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_borrowck/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,18 @@ pub(crate) enum CaptureReasonLabel<'a> {
is_move_msg: bool,
is_loop_message: bool,
},
#[label("help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents")]
#[suggestion(
"consider calling `.as_ref()` to borrow the value's contents",
applicability = "maybe-incorrect",
code = ".as_ref()",
style = "verbose"
)]
#[suggestion(
"consider calling `.as_mut()` to mutably borrow the value's contents",
applicability = "maybe-incorrect",
code = ".as_mut()",
style = "verbose"
)]
BorrowContent {
#[primary_span]
var_span: Span,
Expand Down
126 changes: 124 additions & 2 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use coercion::can_coerce;
use fn_ctxt::FnCtxt;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{HirId, HirIdMap, Node};
Expand Down Expand Up @@ -204,7 +204,9 @@ fn typeck_with_inspect<'tcx>(
);
}

fcx.check_expr_coercible_to_type(body.value, expected_type, None);
fcx.check_expr_coercible_to_type_or_error(body.value, expected_type, None, |err, _| {
extend_err_with_const_context(err, tcx, node, expected_type);
});

fcx.write_ty(id, expected_type);
};
Expand Down Expand Up @@ -274,6 +276,126 @@ fn typeck_with_inspect<'tcx>(
typeck_results
}

fn extend_err_with_const_context(
err: &mut Diag<'_>,
tcx: TyCtxt<'_>,
node: hir::Node<'_>,
expected_ty: Ty<'_>,
) {
match node {
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), .. })
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Const(ty, _, _), ..
}) => {
// Point at the `Type` in `const NAME: Type = value;`.
err.span_label(ty.span, "expected because of the type of the associated constant");
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, ty, _), .. }) => {
// Point at the `Type` in `const NAME: Type = value;`.
err.span_label(ty.span, "expected because of the type of the constant");
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(_, _, ty, _), .. }) => {
// Point at the `Type` in `static NAME: Type = value;`.
err.span_label(ty.span, "expected because of the type of the static");
}
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::Ty(parent) = tcx.parent_hir_node(parent.hir_id)
&& let hir::TyKind::Array(_ty, _len) = parent.kind =>
{
// `[type; len]` in type context.
err.note("array length can only be `usize`");
}
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::Expr(parent) = tcx.parent_hir_node(parent.hir_id)
&& let hir::ExprKind::Repeat(_ty, _len) = parent.kind =>
{
// `[type; len]` in expr context.
err.note("array length can only be `usize`");
}
// FIXME: support method calls too.
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::Expr(expr) = tcx.parent_hir_node(parent.hir_id)
&& let hir::ExprKind::Path(path) = expr.kind
&& let hir::QPath::Resolved(_, path) = path
&& let Res::Def(_, def_id) = path.res =>
{
// `foo<N>()` in expression context, point at `foo`'s const parameter.
if let Some(i) =
path.segments.iter().last().and_then(|segment| segment.args).and_then(|args| {
args.args.iter().position(|arg| {
matches!(arg, hir::GenericArg::Const(arg) if arg.hir_id == parent.hir_id)
})
})
{
let generics = tcx.generics_of(def_id);
let param = &generics.param_at(i, tcx);
let sp = tcx.def_span(param.def_id);
err.span_note(sp, "expected because of the type of the const parameter");
}
}
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::Ty(ty) = tcx.parent_hir_node(parent.hir_id)
&& let hir::TyKind::Path(path) = ty.kind
&& let hir::QPath::Resolved(_, path) = path
&& let Res::Def(_, def_id) = path.res =>
{
// `Foo<N>` in type context, point at `Foo`'s const parameter.
if let Some(i) =
path.segments.iter().last().and_then(|segment| segment.args).and_then(|args| {
args.args.iter().position(|arg| {
matches!(arg, hir::GenericArg::Const(arg) if arg.hir_id == parent.hir_id)
})
})
{
let generics = tcx.generics_of(def_id);
let param = &generics.param_at(i, tcx);
let sp = tcx.def_span(param.def_id);
err.span_note(sp, "expected because of the type of the const parameter");
}
}
hir::Node::AnonConst(anon)
if let hir::Node::Variant(_variant) = tcx.parent_hir_node(anon.hir_id) =>
{
// FIXME: point at `repr` when present in the type.
err.note(
"enum variant discriminant can only be of a primitive type compatible with the \
enum's `repr`",
);
}
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::GenericParam(param) = tcx.parent_hir_node(parent.hir_id)
&& let hir::GenericParamKind::Const { ty, .. } = param.kind =>
{
// `fn foo<const N: usize = ()>` point at the `usize`.
err.span_label(ty.span, "expected because of the type of the const parameter");
}
hir::Node::AnonConst(anon)
if let hir::Node::ConstArg(parent) = tcx.parent_hir_node(anon.hir_id)
&& let hir::Node::TyPat(ty_pat) = tcx.parent_hir_node(parent.hir_id)
&& let hir::Node::Ty(ty) = tcx.parent_hir_node(ty_pat.hir_id)
&& let hir::TyKind::Pat(ty, _) = ty.kind =>
{
// Point at `char` in `pattern_type!(char is 1..=1)`.
err.span_label(ty.span, "the pattern must match the type");
}
hir::Node::AnonConst(anon)
if let hir::Node::Field(_) = tcx.parent_hir_node(anon.hir_id)
&& let ty::Param(_) = expected_ty.kind() =>
{
err.note(
"the type of default fields referencing type parameters can't be assumed inside \
the struct defining them",
);
}
_ => {}
}
}

fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> {
let tcx = fcx.tcx;
let def_id = fcx.body_id;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_macros/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream {
/// Higher-order macro that invokes the specified macro with (a) a list of all query
/// signatures (including modifiers), and (b) a list of non-query names. This allows
/// multiple simpler macros to each have access to these lists.
#[macro_export]
macro_rules! rustc_with_all_queries {
#[rustc_macro_transparency = "semiopaque"] // Use `macro_rules!` hygiene.
pub macro rustc_with_all_queries {
(
// The macro to invoke once, on all queries and non-queries.
$macro:ident!
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ macro_rules! define_dep_nodes {
}

// Create various data structures for each query, and also for a few things that aren't queries.
rustc_with_all_queries! { define_dep_nodes! }
crate::queries::rustc_with_all_queries! { define_dep_nodes! }

// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
// Be very careful changing this type signature!
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ mod macros;

#[macro_use]
pub mod arena;

pub mod dep_graph;
pub mod error;
pub mod hir;
pub mod hooks;
Expand All @@ -76,18 +78,13 @@ pub mod lint;
pub mod metadata;
pub mod middle;
pub mod mir;
pub mod queries;
pub mod query;
pub mod thir;
pub mod traits;
pub mod ty;
pub mod util;
pub mod verify_ich;

#[macro_use]
pub mod query;
#[macro_use]
pub mod queries;
#[macro_use]
pub mod dep_graph;

// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ use crate::mir::mono::{
CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono,
};
use crate::query::describe_as_module;
use crate::query::plumbing::{define_callbacks, query_helper_param_ty};
use crate::traits::query::{
CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal,
CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ pub mod erase;
pub(crate) mod inner;
mod job;
mod keys;
pub(crate) mod modifiers;
pub mod on_disk_cache;
#[macro_use]
pub mod plumbing;
pub(crate) mod modifiers;
mod stack;

pub fn describe_as_module(def_id: impl Into<LocalDefId>, tcx: TyCtxt<'_>) -> String {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,10 @@ macro_rules! define_callbacks {
};
}

// Re-export `macro_rules!` macros as normal items, so that they can be imported normally.
pub(crate) use define_callbacks;
pub(crate) use query_helper_param_ty;

mod sealed {
use rustc_hir::def_id::{LocalModDefId, ModDefId};

Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_mir_build/src/thir/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,7 @@ struct MatchVisitor<'p, 'tcx> {
error: Result<(), ErrorGuaranteed>,
}

// Visitor for a thir body. This calls `check_match`, `check_let` and `check_let_chain` as
// appropriate.
// Visitor for a thir body. This calls `check_match` and `check_let` as appropriate.
impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
fn thir(&self) -> &'p Thir<'tcx> {
self.thir
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_impl/src/dep_kind_vtables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ macro_rules! define_dep_kind_vtables {
// Create an array of vtables, one for each dep kind (non-query and query).
pub fn make_dep_kind_vtables<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindVTable<'tcx>] {
let (nq_vtables, q_vtables) =
rustc_middle::rustc_with_all_queries! { define_dep_kind_vtables! };
rustc_middle::queries::rustc_with_all_queries! { define_dep_kind_vtables! };

// Non-query vtables must come before query vtables, to match the order of `DepKind`.
arena.alloc_from_iter(nq_vtables.into_iter().chain(q_vtables.into_iter()))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_impl/src/query_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,4 +272,4 @@ macro_rules! define_queries {
}
}

rustc_middle::rustc_with_all_queries! { define_queries! }
rustc_middle::queries::rustc_with_all_queries! { define_queries! }
9 changes: 6 additions & 3 deletions compiler/rustc_trait_selection/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1707,7 +1707,8 @@ pub enum TypeErrorAdditionalDiags {
#[suggestion(
"if you meant to write a byte literal, prefix with `b`",
code = "b'{code}'",
applicability = "machine-applicable"
applicability = "machine-applicable",
style = "verbose"
)]
MeantByteLiteral {
#[primary_span]
Expand All @@ -1717,7 +1718,8 @@ pub enum TypeErrorAdditionalDiags {
#[suggestion(
"if you meant to write a `char` literal, use single quotes",
code = "'{code}'",
applicability = "machine-applicable"
applicability = "machine-applicable",
style = "verbose"
)]
MeantCharLiteral {
#[primary_span]
Expand All @@ -1737,7 +1739,8 @@ pub enum TypeErrorAdditionalDiags {
#[suggestion(
"consider specifying the actual array length",
code = "{length}",
applicability = "maybe-incorrect"
applicability = "maybe-incorrect",
style = "verbose"
)]
ConsiderSpecifyingLength {
#[primary_span]
Expand Down
4 changes: 3 additions & 1 deletion src/tools/clippy/tests/ui/track-diagnostics.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> tests/ui/track-diagnostics.rs:LL:CC
|
LL | const S: A = B;
| ^ expected `A`, found `B`
| - ^ expected `A`, found `B`
| |
| expected because of the type of the constant
|
= note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC

Expand Down
5 changes: 5 additions & 0 deletions src/tools/compiletest/src/runtest/rustdoc_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ impl TestCx<'_> {
});

let proc_res = self.document(&out_dir, DocKind::Json);

if !self.config.capture {
writeln!(self.stdout, "{}", proc_res.format_info());
}

if !proc_res.status.success() {
self.fatal_proc_rec("rustdoc failed!", &proc_res);
}
Expand Down
1 change: 1 addition & 0 deletions tests/rustdoc-ui/track-diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ pub const S: A = B;
//~^ ERROR mismatched types
//~| NOTE created at
//~| NOTE expected `A`, found `B`
//~| NOTE expected because of the type of the const
4 changes: 3 additions & 1 deletion tests/rustdoc-ui/track-diagnostics.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/track-diagnostics.rs:LL:CC
|
LL | pub const S: A = B;
| ^ expected `A`, found `B`
| - ^ expected `A`, found `B`
| |
| expected because of the type of the constant
|
= note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC

Expand Down
1 change: 1 addition & 0 deletions tests/ui/array-slice-vec/closure-in-array-len.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ LL | fn([u8; |x: u8| {}]),
|
= note: expected type `usize`
found closure `{closure@$DIR/closure-in-array-len.rs:3:13: 3:20}`
= note: array length can only be `usize`

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ error[E0308]: mismatched types
--> $DIR/subslice-only-once-semantic-restriction.rs:11:30
|
LL | const RECOVERY_WITNESS: () = 0;
| ^ expected `()`, found integer
| -- ^ expected `()`, found integer
| |
| expected because of the type of the constant

error: aborting due to 3 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0308]: mismatched types
--> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:13:21
|
LL | const N: C::M = 4u8;
| ^^^ expected associated type, found `u8`
| ---- ^^^ expected associated type, found `u8`
| |
| expected because of the type of the associated constant
|
= note: expected associated type `<C as O>::M`
found type `u8`
Expand Down
Loading
Loading