Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #95215

Merged
merged 12 commits into from
Mar 22, 2022
Merged
22 changes: 10 additions & 12 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,10 @@ pub struct LocalState<'tcx, Tag: Provenance = AllocId> {
pub enum LocalValue<Tag: Provenance = AllocId> {
/// This local is not currently alive, and cannot be used at all.
Dead,
/// This local is alive but not yet initialized. It can be written to
/// but not read from or its address taken. Locals get initialized on
/// first write because for unsized locals, we do not know their size
/// before that.
Uninitialized,
/// This local is alive but not yet allocated. It cannot be read from or have its address taken,
/// and will be allocated on the first write. This is to support unsized locals, where we cannot
/// know their size in advance.
Unallocated,
/// A normal, live local.
/// Mostly for convenience, we re-use the `Operand` type here.
/// This is an optimization over just always having a pointer here;
Expand All @@ -198,7 +197,7 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> {
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
match self.value {
LocalValue::Dead => throw_ub!(DeadLocal),
LocalValue::Uninitialized => {
LocalValue::Unallocated => {
bug!("The type checker should prevent reading from a never-written local")
}
LocalValue::Live(val) => Ok(val),
Expand All @@ -216,8 +215,7 @@ impl<'tcx, Tag: Provenance + 'static> LocalState<'tcx, Tag> {
match self.value {
LocalValue::Dead => throw_ub!(DeadLocal),
LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
ref mut
local @ (LocalValue::Live(Operand::Immediate(_)) | LocalValue::Uninitialized) => {
ref mut local @ (LocalValue::Live(Operand::Immediate(_)) | LocalValue::Unallocated) => {
Ok(Ok(local))
}
}
Expand Down Expand Up @@ -752,8 +750,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
})?;
}

// Locals are initially uninitialized.
let dummy = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
// Locals are initially unallocated.
let dummy = LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) };
let mut locals = IndexVec::from_elem(dummy, &body.local_decls);

// Now mark those locals as dead that we do not want to initialize
Expand Down Expand Up @@ -921,7 +919,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
trace!("{:?} is now live", local);

let local_val = LocalValue::Uninitialized;
let local_val = LocalValue::Unallocated;
// StorageLive expects the local to be dead, and marks it live.
let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
if !matches!(old, LocalValue::Dead) {
Expand Down Expand Up @@ -1025,7 +1023,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug

match self.ecx.stack()[frame].locals[local].value {
LocalValue::Dead => write!(fmt, " is dead")?,
LocalValue::Uninitialized => write!(fmt, " is uninitialized")?,
LocalValue::Unallocated => write!(fmt, " is unallocated")?,
LocalValue::Live(Operand::Indirect(mplace)) => {
write!(
fmt,
Expand Down
14 changes: 10 additions & 4 deletions compiler/rustc_expand/src/mbe/transcribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ pub(super) fn transcribe<'a>(

// Replace meta-variable expressions with the result of their expansion.
mbe::TokenTree::MetaVarExpr(sp, expr) => {
transcribe_metavar_expr(cx, expr, interp, &repeats, &mut result, &sp)?;
transcribe_metavar_expr(cx, expr, interp, &mut marker, &repeats, &mut result, &sp)?;
}

// If we are entering a new delimiter, we push its contents to the `stack` to be
Expand Down Expand Up @@ -513,17 +513,23 @@ fn transcribe_metavar_expr<'a>(
cx: &ExtCtxt<'a>,
expr: MetaVarExpr,
interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
marker: &mut Marker,
repeats: &[(usize, usize)],
result: &mut Vec<TreeAndSpacing>,
sp: &DelimSpan,
) -> PResult<'a, ()> {
let mut visited_span = || {
let mut span = sp.entire();
marker.visit_span(&mut span);
span
};
match expr {
MetaVarExpr::Count(original_ident, depth_opt) => {
let matched = matched_from_ident(cx, original_ident, interp)?;
let count = count_repetitions(cx, depth_opt, matched, &repeats, sp)?;
let tt = TokenTree::token(
TokenKind::lit(token::Integer, sym::integer(count), None),
sp.entire(),
visited_span(),
);
result.push(tt.into());
}
Expand All @@ -536,7 +542,7 @@ fn transcribe_metavar_expr<'a>(
result.push(
TokenTree::token(
TokenKind::lit(token::Integer, sym::integer(*index), None),
sp.entire(),
visited_span(),
)
.into(),
);
Expand All @@ -548,7 +554,7 @@ fn transcribe_metavar_expr<'a>(
result.push(
TokenTree::token(
TokenKind::lit(token::Integer, sym::integer(*length), None),
sp.entire(),
visited_span(),
)
.into(),
);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir_transform/src/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> {
let l = &frame.locals[local];

if l.value == LocalValue::Uninitialized {
throw_machine_stop_str!("tried to access an uninitialized local")
if l.value == LocalValue::Unallocated {
throw_machine_stop_str!("tried to access an unallocated local")
}

l.access()
Expand Down Expand Up @@ -442,7 +442,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
/// but not reading from them anymore.
fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) {
ecx.frame_mut().locals[local] =
LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) };
LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) };
}

fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
Expand Down Expand Up @@ -1147,7 +1147,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
let frame = self.ecx.frame_mut();
frame.locals[local].value =
if let StatementKind::StorageLive(_) = statement.kind {
LocalValue::Uninitialized
LocalValue::Unallocated
} else {
LocalValue::Dead
};
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,14 @@ impl<'a> Parser<'a> {
Ok(ty) => GenericArg::Type(ty),
Err(err) => {
if is_const_fn {
if let Ok(expr) = (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None)
{
self.restore_snapshot(snapshot);
return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
match (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None) {
Ok(expr) => {
self.restore_snapshot(snapshot);
return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
}
Err(err) => {
err.cancel();
}
}
}
// Try to recover from possible `const` arg without braces.
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_typeck/src/check/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ex.span,
format!("cannot apply unary operator `{}`", op.as_str()),
);
let missing_trait = match op {
hir::UnOp::Deref => unreachable!("check unary op `-` or `!` only"),
hir::UnOp::Not => "std::ops::Not",
hir::UnOp::Neg => "std::ops::Neg",
};
let mut visitor = TypeParamVisitor(vec![]);
visitor.visit_ty(operand_ty);
if let [ty] = &visitor.0[..] {
if let ty::Param(p) = *operand_ty.kind() {
suggest_constraining_param(
self.tcx,
self.body_id,
&mut err,
*ty,
operand_ty,
missing_trait,
p,
true,
);
}
}

let sp = self.tcx.sess.source_map().start_point(ex.span);
if let Some(sp) =
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2030,6 +2030,11 @@ pub fn id() -> u32 {
///
/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
///
/// Because different runtimes have different specifications on the return value
/// of the `main` function, this trait is likely to be available only on
/// standard library's runtime for convenience. Other runtimes are not required
/// to provide similar functionality.
#[cfg_attr(not(test), lang = "termination")]
#[unstable(feature = "termination_trait_lib", issue = "43301")]
#[rustc_on_unimplemented(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// #95163
fn return_ty() -> impl Into<<() as Reexported;
//~^ ERROR expected one of `(`, `::`, `<`, or `>`, found `;`

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: expected one of `(`, `::`, `<`, or `>`, found `;`
--> $DIR/ice-const-generic-function-return-ty.rs:2:46
|
LL | fn return_ty() -> impl Into<<() as Reexported;
| ^ expected one of `(`, `::`, `<`, or `>`

error: aborting due to previous error

6 changes: 6 additions & 0 deletions src/test/ui/type/type-check/missing_trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ fn foo<T>(x: T, y: T) {
fn bar<T>(x: T) {
x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
}

fn baz<T>(x: T) {
let y = -x; //~ ERROR cannot apply unary operator `-` to type `T`
let y = !x; //~ ERROR cannot apply unary operator `!` to type `T`
let y = *x; //~ ERROR type `T` cannot be dereferenced
}
32 changes: 30 additions & 2 deletions src/test/ui/type/type-check/missing_trait_impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,35 @@ help: consider restricting type parameter `T`
LL | fn bar<T: std::ops::AddAssign>(x: T) {
| +++++++++++++++++++++

error: aborting due to 2 previous errors
error[E0600]: cannot apply unary operator `-` to type `T`
--> $DIR/missing_trait_impl.rs:13:13
|
LL | let y = -x;
| ^^ cannot apply unary operator `-`
|
help: consider restricting type parameter `T`
|
LL | fn baz<T: std::ops::Neg<Output = T>>(x: T) {
| +++++++++++++++++++++++++++

error[E0600]: cannot apply unary operator `!` to type `T`
--> $DIR/missing_trait_impl.rs:14:13
|
LL | let y = !x;
| ^^ cannot apply unary operator `!`
|
help: consider restricting type parameter `T`
|
LL | fn baz<T: std::ops::Not<Output = T>>(x: T) {
| +++++++++++++++++++++++++++

error[E0614]: type `T` cannot be dereferenced
--> $DIR/missing_trait_impl.rs:15:13
|
LL | let y = *x;
| ^^

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0368, E0369.
Some errors have detailed explanations: E0368, E0369, E0600, E0614.
For more information about an error, try `rustc --explain E0368`.