Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5b8f281
new branch, fresh git history.
TirushOne Sep 1, 2026
533e60d
Minor cleanup in rustc_hir_analysis::collect
fmease Aug 30, 2026
29d38e4
Support type-relative assoc item paths in generic param defaults & co…
fmease Aug 30, 2026
8f2db6e
Correctly represent doctest source as a `RealFileName` plus line
Urgau Oct 7, 2026
5941c0b
properly ignore the current goal's usages
sjwang05 Oct 8, 2026
f21a12a
In the `BestObligation` prooftree visitor, we now only skip any candi…
LorrensP-2158466 Sep 7, 2026
9bc17fd
Don't rewrite alias outlives in smaller universes
BoxyUwU Oct 7, 2026
7d43809
Produce less general higher ranked alias constraints
BoxyUwU Oct 7, 2026
07d67c6
Better debug impls for abby stuff
BoxyUwU Oct 7, 2026
f4b0976
Fix for const generic parameter checking
Jamesbarford Oct 9, 2026
901cebd
Update tests and create new tests for const generic parameter checking
Jamesbarford Oct 9, 2026
e3941d6
const-eval: ICE when we hit a non-const fn
RalfJung Oct 8, 2026
02dbf08
Allow testing cg-gcc on any target
Kobzol Oct 9, 2026
85b2304
Pass `--remap-path-{prefix,scope}` to the `rustc` doctest invocation
Urgau Oct 7, 2026
47a3f68
Rollup merge of #161998 - fmease:tyrel-in-gen-param-cx, r=jackh726
JonathanBrouwer Oct 9, 2026
e19acff
Rollup merge of #162106 - TirushOne:addr-mutability-suggestions, r=ja…
JonathanBrouwer Oct 9, 2026
62211f6
Rollup merge of #163938 - BoxyUwU:abby_more_correct_alias_rewriting, …
JonathanBrouwer Oct 9, 2026
b1c3947
Rollup merge of #163939 - BoxyUwU:abby_slight_debug_impl_improvements…
JonathanBrouwer Oct 9, 2026
95ddac4
Rollup merge of #163956 - Urgau:rustdoc-doctest-scopes, r=GuillaumeGomez
JonathanBrouwer Oct 9, 2026
6d532f5
Rollup merge of #164042 - Kobzol:cg-gcc-target, r=GuillaumeGomez
JonathanBrouwer Oct 9, 2026
ebb9ae9
Rollup merge of #162443 - LorrensP-2158466:fix-best-obligation-visito…
JonathanBrouwer Oct 9, 2026
f4e76c2
Rollup merge of #162908 - Jamesbarford:fix/const-generic-bug, r=khyperia
JonathanBrouwer Oct 9, 2026
08ae1a9
Rollup merge of #163972 - RalfJung:non-const-eval, r=oli-obk
JonathanBrouwer Oct 9, 2026
6bcaccf
Rollup merge of #164008 - sjwang05:ignore-usages, r=lcnr
JonathanBrouwer Oct 9, 2026
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
13 changes: 10 additions & 3 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,16 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
// all. That said, we have to allow calling functions inside a `const trait`. These
// *are* const-checked!
if !ecx.tcx.is_const_fn(def) || find_attr!(ecx.tcx, def, RustcDoNotConstCheck) {
// We certainly do *not* want to actually call the fn
// though, so be sure we return here.
throw_unsup_format!("calling non-const function `{}`", instance)
// We certainly do *not* want to actually call this fn. const-checking should have
// prevented this, but this can be reached with unleashed-miri, so make testing
// simpler by avoiding ICEs there. (Technically this can still ICE if miri-unleash
// was set in a dependency rather than the current crate. That's okay, it's an
// internal unstable feature.)
if ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
throw_unsup_format!("calling non-const function `{}`", instance)
} else {
span_bug!(ecx.cur_span(), "calling non-const function `{}`", instance)
}
}
}

Expand Down
29 changes: 16 additions & 13 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ fn make_input(early_dcx: &EarlyDiagCtxt, free_matches: &[String]) -> Option<Inpu
.early_fatal("couldn't read from stdin, as it did not contain valid UTF-8");
}

let name = match env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
match env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
Ok(path) => {
let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
"when UNSTABLE_RUSTDOC_TEST_PATH is set \
Expand All @@ -400,12 +400,13 @@ fn make_input(early_dcx: &EarlyDiagCtxt, free_matches: &[String]) -> Option<Inpu
let line = line
.parse::<isize>()
.expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be a number");
FileName::doc_test_source_code(PathBuf::from(path), line)
Some(Input::DocTestStr { file: PathBuf::from(path), line, input })
}
Err(_) => FileName::anon_source_code(&input),
};

Some(Input::Str { name, input })
Err(_) => {
let name = FileName::anon_source_code(&input);
Some(Input::Str { name, input })
}
}
}
[ifile] => Some(Input::File(PathBuf::from(ifile))),
[ifile1, ifile2, ..] => early_dcx.early_fatal(format!(
Expand Down Expand Up @@ -619,7 +620,7 @@ fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
}
safe_println!("{}", String::from_utf8(v).unwrap());
}
Input::Str { .. } => {
Input::Str { .. } | Input::DocTestStr { .. } => {
sess.dcx().fatal("cannot list metadata for stdin");
}
}
Expand Down Expand Up @@ -1373,12 +1374,14 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
Input::File(file) => {
new_parser_from_file(&sess.psess, file, StripTokens::ShebangAndFrontmatter, None)
}
Input::Str { name, input } => new_parser_from_source_str(
&sess.psess,
name.clone(),
input.clone(),
StripTokens::ShebangAndFrontmatter,
),
instr @ (Input::Str { input, .. } | Input::DocTestStr { input, .. }) => {
new_parser_from_source_str(
&sess.psess,
instr.file_name(sess),
input.clone(),
StripTokens::ShebangAndFrontmatter,
)
}
});
parser.parse_inner_attributes()
}
Expand Down
135 changes: 104 additions & 31 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ fn check_method_is_structurally_compatible<'tcx>(
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
compare_number_of_generics(tcx, impl_m, trait_m, delay)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
compare_const_generic_param_types(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
Expand Down Expand Up @@ -2034,31 +2035,8 @@ fn compare_synthetic_generics<'tcx>(
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
}

/// Checks that all parameters in the generics of a given assoc item in a trait impl have
/// the same kind as the respective generic parameter in the trait def.
///
/// For example all 4 errors in the following code are emitted here:
/// ```rust,ignore (pseudo-Rust)
/// trait Foo {
/// fn foo<const N: u8>();
/// type Bar<const N: u8>;
/// fn baz<const N: u32>();
/// type Blah<T>;
/// }
///
/// impl Foo for () {
/// fn foo<const N: u64>() {}
/// //~^ error
/// type Bar<const N: u64> = ();
/// //~^ error
/// fn baz<T>() {}
/// //~^ error
/// type Blah<const N: i64> = u32;
/// //~^ error
/// }
/// ```
///
/// This function does not handle lifetime parameters
/// Checks that corresponding generic parameters in a trait item and its impl
/// are both type parameters or both const parameters.
fn compare_generic_param_kinds<'tcx>(
tcx: TyCtxt<'tcx>,
impl_item: ty::AssocItem,
Expand All @@ -2081,11 +2059,6 @@ fn compare_generic_param_kinds<'tcx>(
{
use GenericParamDefKind::*;
if match (&param_impl.kind, &param_trait.kind) {
(Const { .. }, Const { .. })
if tcx.type_of(param_impl.def_id) != tcx.type_of(param_trait.def_id) =>
{
true
}
(Const { .. }, Type { .. }) | (Type { .. }, Const { .. }) => true,
// this is exhaustive so that anyone adding new generic param kinds knows
// to make sure this error is reported for them.
Expand All @@ -2104,7 +2077,7 @@ fn compare_generic_param_kinds<'tcx>(
"{} `{}` has an incompatible generic parameter for trait `{}`",
impl_item.descr(),
trait_item.name(),
&tcx.def_path_str(tcx.parent(trait_item.def_id))
tcx.def_path_str(tcx.parent(trait_item.def_id))
);

let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind {
Expand Down Expand Up @@ -2138,6 +2111,98 @@ fn compare_generic_param_kinds<'tcx>(
Ok(())
}

/// Checks that corresponding const generic parameters in a trait item and its
/// impl have compatible types.
fn compare_const_generic_param_types<'tcx>(
tcx: TyCtxt<'tcx>,
impl_item: ty::AssocItem,
trait_item: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
assert_eq!(impl_item.tag(), trait_item.tag());
use GenericParamDefKind::*;

let const_params_of = |def_id| {
tcx.generics_of(def_id).own_params.iter().filter(|param| matches!(param.kind, Const { .. }))
};

// Map the trait item's generic parameters into the impl item's generic context.
let trait_to_impl_args = ty::GenericArgs::identity_for_item(tcx, impl_item.def_id).rebase_onto(
tcx,
impl_item.container_id(tcx),
impl_trait_ref.args,
);
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let param_env = tcx.param_env(impl_item.def_id);

let param_iter =
iter::zip(const_params_of(impl_item.def_id), const_params_of(trait_item.def_id));

for (param_impl, param_trait) in param_iter {
let param_impl_ty_span = tcx.ty_span(param_impl.def_id.expect_local());

let cause = ObligationCause::new(
param_impl_ty_span,
impl_item.def_id.expect_local(),
ObligationCauseCode::CompareImplItem {
impl_item_def_id: impl_item.def_id.expect_local(),
trait_item_def_id: trait_item.def_id,
kind: impl_item.kind,
},
);

let impl_ty =
ocx.normalize(&cause, param_env, tcx.type_of(param_impl.def_id).instantiate_identity());

let trait_ty = ocx.normalize(
&cause,
param_env,
tcx.type_of(param_trait.def_id).instantiate(tcx, trait_to_impl_args),
);

match ocx.eq(&cause, param_env, trait_ty, impl_ty) {
// Despite returning `Ok` all may not be well. As such, outside of this
// loop we invoke `ocx.evaluate_obligations_error_on_ambiguity()` to check
// for any other errors that may have occurred.
Ok(_) => {}
Err(terr) => {
let param_trait_ty_span =
param_trait.def_id.as_local().map(|def_id| tcx.ty_span(def_id));
let mut diag = struct_span_code_err!(
tcx.dcx(),
param_impl_ty_span,
E0053,
"{} `{}` has an incompatible type for const generic parameter",
trait_item.descr(),
trait_item.name(),
);
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
param_trait_ty_span.map(|span| (span, Cow::from("type in trait"), false)),
Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_ty.into(),
found: impl_ty.into(),
}))),
terr,
false,
None,
);
let reported = diag.emit_err_unless_delay(delay);
return Err(reported);
}
}
}

if let TraitErrors::HasErrors(errors) = ocx.evaluate_obligations_error_on_ambiguity() {
Err(infcx.err_ctxt().report_fulfillment_errors(errors))
} else {
Ok(())
}
}

fn compare_impl_const<'tcx>(
tcx: TyCtxt<'tcx>,
impl_const_item: ty::AssocItem,
Expand All @@ -2147,6 +2212,13 @@ fn compare_impl_const<'tcx>(
compare_const_directness(tcx, impl_const_item, trait_const_item)?;
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
compare_const_generic_param_types(
tcx,
impl_const_item,
trait_const_item,
impl_trait_ref,
false,
)?;
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
compare_const_clause_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
}
Expand Down Expand Up @@ -2325,6 +2397,7 @@ fn compare_impl_ty<'tcx>(
) -> Result<(), ErrorGuaranteed> {
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
compare_const_generic_param_types(tcx, impl_ty, trait_ty, impl_trait_ref, false)?;
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
compare_type_clause_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)
Expand Down
25 changes: 12 additions & 13 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1760,28 +1760,27 @@ fn rendered_precise_capturing_args<'tcx>(

fn const_param_default<'tcx>(
tcx: TyCtxt<'tcx>,
local_def_id: LocalDefId,
param_def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
let hir::Node::GenericParam(hir::GenericParam {
kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
..
}) = tcx.hir_node_by_def_id(local_def_id)
}) = tcx.hir_node_by_def_id(param_def_id)
else {
span_bug!(
tcx.def_span(local_def_id),
"`const_param_default` expected a generic parameter with a constant"
tcx.def_span(param_def_id),
"const_param_default: expected a const parameter with a default value"
)
};

let icx = ItemCtxt::new(tcx, local_def_id);
// FIXME: Don't lower in the context of parent. Blocked on the removal of GCE. See comment in
// `type_of.rs` for details (Ctrl+F for `generics_of`).
let item_def_id = tcx.local_parent(param_def_id);
let icx = ItemCtxt::new(tcx, item_def_id);

let def_id = local_def_id.to_def_id();
let identity_args = ty::GenericArgs::identity_for_item(tcx, tcx.parent(def_id));

let ct = icx.lowerer().lower_const_arg(
default_ct,
tcx.type_of(def_id).instantiate(tcx, identity_args).skip_norm_wip(),
);
let ct = icx
.lowerer()
.lower_const_arg(ct, tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip());
ty::EarlyBinder::bind(tcx, ct)
}

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
Node::Item(_) | Node::ForeignItem(_) => None,

// Params don't really have generics, but we use it when instantiating their value paths.
// FIXME: Use the HIR parent here similar to `Node::Field`. Blocked on the removal of GCE,
// see comment in `type_of.rs` for details (Ctrl+F for `generics_of`).
Node::GenericParam(_) => None,

Node::Synthetic => span_bug!(
Expand All @@ -236,7 +238,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let opt_self = if let Node::Item(item) = node
&& let ItemKind::Trait { .. } | ItemKind::TraitAlias(..) = item.kind
{
// Something of a hack: We reuse the node ID of the trait for the self type parameter.
// Something of a hack: We reuse the DefId of the trait for the self type parameter.
Some(ty::GenericParamDef {
index: 0,
name: kw::SelfUpper,
Expand Down
30 changes: 19 additions & 11 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
None => {}
}

let hir_id = tcx.local_def_id_to_hir_id(def_id);

let icx = ItemCtxt::new(tcx, def_id);

let new_bound_fn_def = |hir: HirId, did| {
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
Ty::new_fn_def(
Expand All @@ -80,7 +76,21 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
)
};

let output = match tcx.hir_node(hir_id) {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let hir_node = tcx.hir_node(hir_id);
let def_id = match hir_node {
// For generic params, we lower in the context of the overarching item to be able to resolve
// type-relative paths in type param defaults & const param types.
// FIXME: Remove this special case again & simply set the `Generics.parent` for generic
// params in `generics_of` similar to struct fields. However, that's blocked on the
// removal of GCE in favor of mGCA. Doing this change now would introduce tons of
// query cycles for GCE.
Node::GenericParam(_) => tcx.local_parent(def_id),
_ => def_id,
};
let icx = ItemCtxt::new(tcx, def_id);

let output = match hir_node {
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(_, _) => new_bound_fn_def(item.hir_id(), def_id.to_def_id()),
TraitItemKind::Const(ty, rhs) => rhs
Expand All @@ -104,7 +114,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
.unwrap_or_else(|| icx.lower_ty(ty)),
TraitItemKind::Type(_, Some(ty)) => icx.lower_ty(ty),
TraitItemKind::Type(_, None) => {
span_bug!(item.span, "associated type missing default");
span_bug!(item.span, "type_of: associated type missing default");
}
},

Expand Down Expand Up @@ -207,7 +217,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
| ItemKind::ExternCrate(..)
| ItemKind::Use(..)
| ItemKind::TestBinderConstraints { .. } => {
span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind);
span_bug!(item.span, "type_of: unexpected item kind: {:?}", item.kind);
}
},

Expand Down Expand Up @@ -263,12 +273,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
lowered_ty
}
}
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
_ => bug!("type_of: unexpected node kind {hir_node:?}"),
},

x => {
bug!("unexpected sort of node in type_of(): {:?}", x);
}
node => bug!("type_of: unexpected node kind: {node:?}"),
};
if let Err(e) = icx.check_tainted_by_errors()
&& !output.references_error()
Expand Down
Loading
Loading