Skip to content

Commit

Permalink
Auto merge of rust-lang#71958 - Dylan-DPC:rollup-woxwt5d, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - rust-lang#70908 (Provide suggestions for type parameters missing bounds for associated types)
 - rust-lang#71731 (Turn off rustc-dev-guide toolstate for now)
 - rust-lang#71888 (refactor suggest_traits_to_import)
 - rust-lang#71918 (Rename methods section)
 - rust-lang#71950 (Miri validation error handling cleanup)

Failed merges:

r? @ghost
  • Loading branch information
bors committed May 6, 2020
2 parents 1836e3b + 066eb08 commit 29457dd
Show file tree
Hide file tree
Showing 38 changed files with 950 additions and 485 deletions.
2 changes: 1 addition & 1 deletion src/bootstrap/toolstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static STABLE_TOOLS: &[(&str, &str)] = &[
static NIGHTLY_TOOLS: &[(&str, &str)] = &[
("miri", "src/tools/miri"),
("embedded-book", "src/doc/embedded-book"),
("rustc-dev-guide", "src/doc/rustc-dev-guide"),
// ("rustc-dev-guide", "src/doc/rustc-dev-guide"),
];

fn print_error(tool: &str, submodule: &str) {
Expand Down
1 change: 0 additions & 1 deletion src/ci/docker/x86_64-gnu-tools/checktools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ python3 "$X_PY" test --no-fail-fast \
src/doc/rust-by-example \
src/doc/embedded-book \
src/doc/edition-guide \
src/doc/rustc-dev-guide \
src/tools/clippy \
src/tools/rls \
src/tools/rustfmt \
Expand Down
96 changes: 85 additions & 11 deletions src/librustc_ast_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use rustc_session::Session;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use std::mem;
use std::ops::DerefMut;

const MORE_EXTERN: &str =
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
Expand Down Expand Up @@ -1113,17 +1114,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {

for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
self.err_handler()
.struct_span_err(
predicate.span,
"equality constraints are not yet supported in `where` clauses",
)
.span_label(predicate.span, "not supported")
.note(
"see issue #20041 <https://github.com/rust-lang/rust/issues/20041> \
for more information",
)
.emit();
deny_equality_constraints(self, predicate, generics);
}
}

Expand Down Expand Up @@ -1300,6 +1291,89 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}

/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
/// like it's setting an associated type, provide an appropriate suggestion.
fn deny_equality_constraints(
this: &mut AstValidator<'_>,
predicate: &WhereEqPredicate,
generics: &Generics,
) {
let mut err = this.err_handler().struct_span_err(
predicate.span,
"equality constraints are not yet supported in `where` clauses",
);
err.span_label(predicate.span, "not supported");

// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
if let TyKind::Path(None, path) = &qself.ty.kind {
match &path.segments[..] {
[PathSegment { ident, args: None, .. }] => {
for param in &generics.params {
if param.ident == *ident {
let param = ident;
match &full_path.segments[qself.position..] {
[PathSegment { ident, .. }] => {
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
let mut assoc_path = full_path.clone();
// Remove `Bar` from `Foo::Bar`.
assoc_path.segments.pop();
let len = assoc_path.segments.len() - 1;
// Build `<Bar = RhsTy>`.
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
id: rustc_ast::node_id::DUMMY_NODE_ID,
ident: *ident,
kind: AssocTyConstraintKind::Equality {
ty: predicate.rhs_ty.clone(),
},
span: ident.span,
});
// Add `<Bar = RhsTy>` to `Foo`.
match &mut assoc_path.segments[len].args {
Some(args) => match args.deref_mut() {
GenericArgs::Parenthesized(_) => continue,
GenericArgs::AngleBracketed(args) => {
args.args.push(arg);
}
},
empty_args => {
*empty_args = AngleBracketedArgs {
span: ident.span,
args: vec![arg],
}
.into();
}
}
err.span_suggestion_verbose(
predicate.span,
&format!(
"if `{}` is an associated type you're trying to set, \
use the associated type binding syntax",
ident
),
format!(
"{}: {}",
param,
pprust::path_to_string(&assoc_path)
),
Applicability::MaybeIncorrect,
);
}
_ => {}
};
}
}
}
_ => {}
}
}
}
err.note(
"see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
);
err.emit();
}

pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
let mut validator = AstValidator {
session,
Expand Down
36 changes: 35 additions & 1 deletion src/librustc_hir/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2626,8 +2626,42 @@ impl Node<'_> {
match self {
Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. })
| Node::Item(Item { kind: ItemKind::Fn(_, generics, _), .. }) => Some(generics),
| Node::Item(Item {
kind:
ItemKind::Trait(_, _, generics, ..)
| ItemKind::Impl { generics, .. }
| ItemKind::Fn(_, generics, _),
..
}) => Some(generics),
_ => None,
}
}

pub fn hir_id(&self) -> Option<HirId> {
match self {
Node::Item(Item { hir_id, .. })
| Node::ForeignItem(ForeignItem { hir_id, .. })
| Node::TraitItem(TraitItem { hir_id, .. })
| Node::ImplItem(ImplItem { hir_id, .. })
| Node::Field(StructField { hir_id, .. })
| Node::AnonConst(AnonConst { hir_id, .. })
| Node::Expr(Expr { hir_id, .. })
| Node::Stmt(Stmt { hir_id, .. })
| Node::Ty(Ty { hir_id, .. })
| Node::Binding(Pat { hir_id, .. })
| Node::Pat(Pat { hir_id, .. })
| Node::Arm(Arm { hir_id, .. })
| Node::Block(Block { hir_id, .. })
| Node::Local(Local { hir_id, .. })
| Node::MacroDef(MacroDef { hir_id, .. })
| Node::Lifetime(Lifetime { hir_id, .. })
| Node::Param(Param { hir_id, .. })
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
Node::Variant(Variant { id, .. }) => Some(*id),
Node::Ctor(variant) => variant.ctor_hir_id(),
Node::Crate(_) | Node::Visibility(_) => None,
}
}
}
19 changes: 14 additions & 5 deletions src/librustc_middle/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use super::{AllocId, Pointer, RawConst, ScalarMaybeUndef};
use crate::mir::interpret::ConstValue;
use crate::ty::layout::LayoutError;
use crate::ty::query::TyCtxtAt;
use crate::ty::tls;
use crate::ty::{self, layout, Ty};
use crate::ty::{self, layout, tls, FnSig, Ty};

use rustc_data_structures::sync::Lock;
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorReported};
Expand Down Expand Up @@ -329,7 +328,7 @@ impl fmt::Display for CheckInAllocMsg {
}

/// Error information for when the program caused Undefined Behavior.
pub enum UndefinedBehaviorInfo {
pub enum UndefinedBehaviorInfo<'tcx> {
/// Free-form case. Only for errors that are never caught!
Ub(String),
/// Unreachable code was executed.
Expand All @@ -347,6 +346,8 @@ pub enum UndefinedBehaviorInfo {
PointerArithOverflow,
/// Invalid metadata in a wide pointer (using `str` to avoid allocations).
InvalidMeta(&'static str),
/// Invalid drop function in vtable.
InvalidDropFn(FnSig<'tcx>),
/// Reading a C string that does not end within its allocation.
UnterminatedCString(Pointer),
/// Dereferencing a dangling pointer after it got freed.
Expand Down Expand Up @@ -380,6 +381,8 @@ pub enum UndefinedBehaviorInfo {
InvalidDiscriminant(ScalarMaybeUndef),
/// Using a pointer-not-to-a-function as function pointer.
InvalidFunctionPointer(Pointer),
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
InvalidUndefBytes(Option<Pointer>),
/// Working with a local that is not currently live.
Expand All @@ -391,7 +394,7 @@ pub enum UndefinedBehaviorInfo {
},
}

impl fmt::Display for UndefinedBehaviorInfo {
impl fmt::Display for UndefinedBehaviorInfo<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use UndefinedBehaviorInfo::*;
match self {
Expand All @@ -404,6 +407,11 @@ impl fmt::Display for UndefinedBehaviorInfo {
RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg),
InvalidDropFn(sig) => write!(
f,
"invalid drop function signature: got {}, expected exactly one argument which must be a pointer type",
sig
),
UnterminatedCString(p) => write!(
f,
"reading a null-terminated string starting at {} with no null found before end of allocation",
Expand Down Expand Up @@ -446,6 +454,7 @@ impl fmt::Display for UndefinedBehaviorInfo {
InvalidFunctionPointer(p) => {
write!(f, "using {} as function pointer but it does not point to a function", p)
}
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
InvalidUndefBytes(Some(p)) => write!(
f,
"reading uninitialized memory at {}, but this operation requires initialized memory",
Expand Down Expand Up @@ -549,7 +558,7 @@ impl dyn MachineStopType {

pub enum InterpError<'tcx> {
/// The program caused undefined behavior.
UndefinedBehavior(UndefinedBehaviorInfo),
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
/// The program did something the interpreter does not support (some of these *might* be UB
/// but the interpreter is not sure).
Unsupported(UnsupportedOpInfo),
Expand Down
Loading

0 comments on commit 29457dd

Please sign in to comment.