Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 7 additions & 3 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1269,9 +1269,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
GenericArg::Type(self.lower_ty_alloc(ty, itctx).try_as_ambig_ty().unwrap())
}
ast::GenericArg::Const(ct) => GenericArg::Const(
self.lower_anon_const_to_const_arg_and_alloc(ct).try_as_ambig_ct().unwrap(),
),
ast::GenericArg::Const(ct) => {
let ct = self.lower_anon_const_to_const_arg_and_alloc(ct);
match ct.try_as_ambig_ct() {
Some(ct) => GenericArg::Const(ct),
None => GenericArg::Infer(hir::InferArg { hir_id: ct.hir_id, span: ct.span }),
}
}
}
}

Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,23 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
TokenTree::Token(token, spacing) => {
let token_str = self.token_to_string_ext(token, convert_dollar_crate);
self.word(token_str);
// Emit hygiene annotations for identity-bearing tokens,
// matching how print_ident() and print_lifetime() call ann_post().
match token.kind {
token::Ident(name, _) => {
self.ann_post(Ident::new(name, token.span));
}
token::NtIdent(ident, _) => {
self.ann_post(ident);
}
token::Lifetime(name, _) => {
self.ann_post(Ident::new(name, token.span));
}
token::NtLifetime(ident, _) => {
self.ann_post(ident);
}
_ => {}
}
if let token::DocComment(..) = token.kind {
self.hardbreak()
}
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2874,6 +2874,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
) -> Const<'tcx> {
let tcx = self.tcx();

let ty = if !ty.has_infer() { Some(ty) } else { None };

if let LitKind::Err(guar) = *kind {
return ty::Const::new_error(tcx, guar);
}
Expand Down Expand Up @@ -2905,16 +2908,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
};

let lit_input = match expr.kind {
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: false }),
hir::ExprKind::Lit(lit) => {
Some(LitToConstInput { lit: lit.node, ty: Some(ty), neg: false })
}
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: lit.node, ty, neg: true }),
hir::ExprKind::Lit(lit) => {
Some(LitToConstInput { lit: lit.node, ty: Some(ty), neg: true })
}
_ => None,
},
_ => None,
};

lit_input.and_then(|l| {
if const_lit_matches_ty(tcx, &l.lit, l.ty, l.neg) {
if const_lit_matches_ty(tcx, &l.lit, ty, l.neg) {
tcx.at(expr.span)
.lit_to_const(l)
.map(|value| ty::Const::new_value(tcx, value.valtree, value.ty))
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_lint/src/for_loops_over_fallibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let Some((pat, arg)) = extract_for_loop(expr) else { return };

// Do not put suggestions for external macros.
if pat.span.from_expansion() {
return;
}

let arg_span = arg.span.source_callsite();

let ty = cx.typeck_results().expr_ty(arg);
Expand Down Expand Up @@ -77,6 +82,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
};

let sub = if let Some(recv) = extract_iterator_next_call(cx, arg)
&& recv.span.can_be_used_for_suggestions()
&& recv.span.between(arg_span.shrink_to_hi()).can_be_used_for_suggestions()
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
{
ForLoopsOverFalliblesLoopSub::RemoveNext {
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_middle/src/ty/consts/lit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ pub struct LitToConstInput<'tcx> {
/// The absolute value of the resultant constant.
pub lit: LitKind,
/// The type of the constant.
pub ty: Ty<'tcx>,
///
/// `None` is used by const generics when the type of the constant is unknown, e.g.
/// if there are inference variables
pub ty: Option<Ty<'tcx>>,
/// If the constant is negative.
pub neg: bool,
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_mir_build/src/builder/expr/as_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ pub(crate) fn as_constant_inner<'tcx>(

match *kind {
ExprKind::Literal { lit, neg } => {
let const_ = lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty, neg });
let const_ =
lit_to_mir_constant(tcx, LitToConstInput { lit: lit.node, ty: Some(ty), neg });

ConstOperand { span, user_ty: None, const_ }
}
Expand Down Expand Up @@ -109,6 +110,8 @@ pub(crate) fn as_constant_inner<'tcx>(
fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>) -> Const<'tcx> {
let LitToConstInput { lit, ty, neg } = lit_input;

let ty = ty.expect("type of literal must be known at this point");

if let Err(guar) = ty.error_reported() {
return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar));
}
Expand Down
22 changes: 12 additions & 10 deletions compiler/rustc_mir_build/src/thir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,27 @@ pub(crate) fn lit_to_const<'tcx>(
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result))
};

let (valtree, valtree_ty) = match (lit, expected_ty.kind()) {
let (valtree, valtree_ty) = match (lit, expected_ty.map(|ty| ty.kind())) {
(ast::LitKind::Str(s, _), _) => {
let str_bytes = s.as_str().as_bytes();
let valtree_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_);
(ty::ValTree::from_raw_bytes(tcx, str_bytes), valtree_ty)
}
(ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
(ast::LitKind::ByteStr(byte_sym, _), Some(ty::Ref(_, inner_ty, _)))
if let ty::Slice(ty) | ty::Array(ty, _) = inner_ty.kind()
&& let ty::Uint(UintTy::U8) = ty.kind() =>
{
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
}
(ast::LitKind::ByteStr(byte_sym, _), ty::Slice(inner_ty) | ty::Array(inner_ty, _))
if tcx.features().deref_patterns()
&& let ty::Uint(UintTy::U8) = inner_ty.kind() =>
(
ast::LitKind::ByteStr(byte_sym, _),
Some(ty::Slice(inner_ty) | ty::Array(inner_ty, _)),
) if tcx.features().deref_patterns()
&& let ty::Uint(UintTy::U8) = inner_ty.kind() =>
{
// Byte string literal patterns may have type `[u8]` or `[u8; N]` if `deref_patterns` is
// enabled, in order to allow, e.g., `deref!(b"..."): Vec<u8>`.
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty)
(ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str()), expected_ty.unwrap())
}
(ast::LitKind::ByteStr(byte_sym, _), _) => {
let valtree = ty::ValTree::from_raw_bytes(tcx, byte_sym.as_byte_str());
Expand Down Expand Up @@ -79,11 +81,11 @@ pub(crate) fn lit_to_const<'tcx>(
trunc(if neg { u128::wrapping_neg(n.get()) } else { n.get() }, i.to_unsigned());
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_int(tcx, i))
}
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Uint(ui)) if !neg => {
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Uint(ui))) if !neg => {
let scalar_int = trunc(n.get(), *ui);
(ty::ValTree::from_scalar_int(tcx, scalar_int), Ty::new_uint(tcx, *ui))
}
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), ty::Int(i)) => {
(ast::LitKind::Int(n, ast::LitIntType::Unsuffixed), Some(ty::Int(i))) => {
// Unsigned "negation" has the same bitwise effect as signed negation,
// which gets the result we want without additional casts.
let scalar_int =
Expand All @@ -101,7 +103,7 @@ pub(crate) fn lit_to_const<'tcx>(
let bits = parse_float_into_scalar(n, fty, neg)?;
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, fty))
}
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), ty::Float(fty)) => {
(ast::LitKind::Float(n, ast::LitFloatType::Unsuffixed), Some(ty::Float(fty))) => {
let bits = parse_float_into_scalar(n, *fty, neg)?;
(ty::ValTree::from_scalar_int(tcx, bits), Ty::new_float(tcx, *fty))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/pattern/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ impl<'tcx> PatCtxt<'tcx> {
// patterns to `str`, and byte-string literal patterns to `[u8; N]` or `[u8]`.

let pat_ty = self.typeck_results.node_type(pat.hir_id);
let lit_input = LitToConstInput { lit: lit.node, ty: pat_ty, neg: *negated };
let lit_input = LitToConstInput { lit: lit.node, ty: Some(pat_ty), neg: *negated };
let constant = const_lit_matches_ty(self.tcx, &lit.node, pat_ty, *negated)
.then(|| self.tcx.at(expr.span).lit_to_const(lit_input))
.flatten()
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ty_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ fn recurse_build<'tcx>(
}
&ExprKind::Literal { lit, neg } => {
let sp = node.span;
match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: node.ty, neg }) {
match tcx.at(sp).lit_to_const(LitToConstInput { lit: lit.node, ty: Some(node.ty), neg })
{
Some(value) => ty::Const::new_value(tcx, value.valtree, value.ty),
None => ty::Const::new_misc_error(tcx),
}
Expand Down
11 changes: 11 additions & 0 deletions src/bootstrap/src/utils/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! relevant to command execution in the bootstrap process. This includes settings such as
//! dry-run mode, verbosity level, and failure behavior.

use std::backtrace::{Backtrace, BacktraceStatus};
use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Formatter};
Expand Down Expand Up @@ -930,6 +931,16 @@ Executed at: {executed_at}"#,
if stderr.captures() {
writeln!(error_message, "\n--- STDERR vvv\n{}", output.stderr().trim()).unwrap();
}
let backtrace = if exec_ctx.verbosity > 1 {
Backtrace::force_capture()
} else if matches!(command.failure_behavior, BehaviorOnFailure::Ignore) {
Backtrace::disabled()
} else {
Backtrace::capture()
};
if matches!(backtrace.status(), BacktraceStatus::Captured) {
writeln!(error_message, "\n--- BACKTRACE vvv\n{backtrace}").unwrap();
}

match command.failure_behavior {
BehaviorOnFailure::DelayFail => {
Expand Down
14 changes: 0 additions & 14 deletions tests/crashes/147973.rs

This file was deleted.

9 changes: 9 additions & 0 deletions tests/ui/const-generics/mgca/braced-const-infer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Regression test for https://github.com/rust-lang/rust/issues/153198
#![feature(min_generic_const_args)]
#![allow(incomplete_features, rust_2021_compatibility)]

trait Trait<T> {}

impl dyn Trait<{_}> {} //~ ERROR: the placeholder `_` is not allowed within types on item signatures

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/const-generics/mgca/braced-const-infer.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations
--> $DIR/braced-const-infer.rs:7:17
|
LL | impl dyn Trait<{_}> {}
| ^ not allowed in type signatures

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0121`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! This test ensures compilation failure when trying to pass literals
//! without explicitly stated type as inference variables in generic arguments.
//!
//! See https://github.com/rust-lang/rust/pull/153557

#![allow(incomplete_features)]
#![feature(adt_const_params, min_generic_const_args, generic_const_parameter_types)]

fn main() {
foo::<_, { 2 }>();
//~^ ERROR: type annotations needed for the literal
let _: PC<_, { 42 }> = PC { a: 1, b: 1 };
//~^ ERROR: type annotations needed for the literal
}

struct PC<T, const N: T> {
//~^ ERROR: `T` can't be used as a const parameter type [E0741]
a: T,
}

fn foo<const N: usize, const A: [u8; N]>() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0741]: `T` can't be used as a const parameter type
--> $DIR/infer-vars-in-const-args-conflicting.rs:16:23
|
LL | struct PC<T, const N: T> {
| ^

error: type annotations needed for the literal
--> $DIR/infer-vars-in-const-args-conflicting.rs:10:16
|
LL | foo::<_, { 2 }>();
| ^

error: type annotations needed for the literal
--> $DIR/infer-vars-in-const-args-conflicting.rs:12:20
|
LL | let _: PC<_, { 42 }> = PC { a: 1, b: 1 };
| ^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0741`.
22 changes: 22 additions & 0 deletions tests/ui/const-generics/mgca/infer-vars-in-const-args-correct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! This test ensures no errors are emitted when lowering literals with
//! explicitly stated types and inference variables in the type of the const
//! generic parameter.
//!
//! See https://github.com/rust-lang/rust/pull/153557

//@check-pass

#![allow(incomplete_features)]
#![feature(adt_const_params,
min_generic_const_args,
generic_const_parameter_types,
unsized_const_params
)]

use std::marker::ConstParamTy_;

fn main() {
foo::<_, 2_i32>();
}

fn foo<T: ConstParamTy_, const N: T>() {}
20 changes: 20 additions & 0 deletions tests/ui/const-generics/mgca/macro-const-arg-infer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! Regression test for https://github.com/rust-lang/rust/issues/153198
#![feature(min_generic_const_args)]
#![allow(incomplete_features)]
macro_rules! y {
( $($matcher:tt)*) => {
_ //~ ERROR: the placeholder `_` is not allowed within types on item signatures
};
}

struct A<T>; //~ ERROR: type parameter `T` is never used

const y: A<
{
y! {
x
}
},
> = 1; //~ ERROR: mismatched types

fn main() {}
44 changes: 44 additions & 0 deletions tests/ui/const-generics/mgca/macro-const-arg-infer.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
error[E0392]: type parameter `T` is never used
--> $DIR/macro-const-arg-infer.rs:10:10
|
LL | struct A<T>;
| ^ unused type parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead

error[E0308]: mismatched types
--> $DIR/macro-const-arg-infer.rs:18:5
|
LL | const y: A<
| __________-
LL | | {
LL | | y! {
LL | | x
LL | | }
LL | | },
LL | | > = 1;
| | - ^ expected `A<_>`, found integer
| |_|
| expected because of the type of the constant
|
= note: expected struct `A<_>`
found type `{integer}`

error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
--> $DIR/macro-const-arg-infer.rs:6:9
|
LL | _
| ^ not allowed in type signatures
...
LL | / y! {
LL | | x
LL | | }
| |_________- in this macro invocation
|
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0121, E0308, E0392.
For more information about an error, try `rustc --explain E0121`.
Loading
Loading