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 #80568

Closed
wants to merge 10 commits into from
56 changes: 31 additions & 25 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -717,35 +717,46 @@ impl<'a> AstValidator<'a> {

/// Checks that generic parameters are in the correct order,
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
fn validate_generic_param_order<'a>(
fn validate_generic_param_order(
sess: &Session,
handler: &rustc_errors::Handler,
generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
generics: &[GenericParam],
span: Span,
) {
let mut max_param: Option<ParamKindOrd> = None;
let mut out_of_order = FxHashMap::default();
let mut param_idents = vec![];

for (kind, bounds, span, ident) in generics {
for param in generics {
let ident = Some(param.ident.to_string());
let (kind, bounds, span) = (&param.kind, Some(&*param.bounds), param.ident.span);
let (ord_kind, ident) = match &param.kind {
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
GenericParamKind::Const { ref ty, kw_span: _ } => {
let ty = pprust::ty_to_string(ty);
let unordered = sess.features_untracked().const_generics;
(ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
}
};
if let Some(ident) = ident {
param_idents.push((kind, bounds, param_idents.len(), ident));
param_idents.push((kind, ord_kind, bounds, param_idents.len(), ident));
}
let max_param = &mut max_param;
match max_param {
Some(max_param) if *max_param > kind => {
let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
Some(max_param) if *max_param > ord_kind => {
let entry = out_of_order.entry(ord_kind).or_insert((*max_param, vec![]));
entry.1.push(span);
}
Some(_) | None => *max_param = Some(kind),
Some(_) | None => *max_param = Some(ord_kind),
};
}

let mut ordered_params = "<".to_string();
if !out_of_order.is_empty() {
param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i));
let mut first = true;
for (_, bounds, _, ident) in param_idents {
for (kind, _, bounds, _, ident) in param_idents {
if !first {
ordered_params += ", ";
}
Expand All @@ -756,6 +767,16 @@ fn validate_generic_param_order<'a>(
ordered_params += &pprust::bounds_to_string(&bounds);
}
}
match kind {
GenericParamKind::Type { default: Some(default) } => {
ordered_params += " = ";
ordered_params += &pprust::ty_to_string(default);
}
GenericParamKind::Type { default: None } => (),
GenericParamKind::Lifetime => (),
// FIXME(const_generics:defaults)
GenericParamKind::Const { ty: _, kw_span: _ } => (),
}
first = false;
}
}
Expand Down Expand Up @@ -1150,22 +1171,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
validate_generic_param_order(
self.session,
self.err_handler(),
generics.params.iter().map(|param| {
let ident = Some(param.ident.to_string());
let (kind, ident) = match &param.kind {
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
GenericParamKind::Const { ref ty, kw_span: _ } => {
let ty = pprust::ty_to_string(ty);
let unordered = self.session.features_untracked().const_generics;
(
ParamKindOrd::Const { unordered },
Some(format!("const {}: {}", param.ident, ty)),
)
}
};
(kind, Some(&*param.bounds), param.ident.span, ident)
}),
&generics.params,
generics.span,
);

Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
//! Codegen the completed AST to the LLVM IR.
//!
//! Some functions here, such as codegen_block and codegen_expr, return a value --
//! the result of the codegen to LLVM -- while others, such as codegen_fn
//! and mono_item, are called only for the side effect of adding a
//! particular definition to the LLVM IR output we're producing.
//! Codegen the MIR to the LLVM IR.
//!
//! Hopefully useful general knowledge about codegen:
//!
//! * There's no way to find out the `Ty` type of a Value. Doing so
//! * There's no way to find out the [`Ty`] type of a [`Value`]. Doing so
//! would be "trying to get the eggs out of an omelette" (credit:
//! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
//! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
//! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
//! pcwalton). You can, instead, find out its [`llvm::Type`] by calling [`val_ty`],
//! but one [`llvm::Type`] corresponds to many [`Ty`]s; for instance, `tup(int, int,
//! int)` and `rec(x=int, y=int, z=int)` will have the same [`llvm::Type`].
//!
//! [`Ty`]: rustc_middle::ty::Ty
//! [`val_ty`]: common::val_ty

use super::ModuleLlvm;

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}
}

/// Get the [LLVM type][Type] of a [`Value`].
pub fn val_ty(v: &Value) -> &Type {
unsafe { llvm::LLVMTypeOf(v) }
}
Expand Down
15 changes: 0 additions & 15 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
//! Codegen the completed AST to the LLVM IR.
//!
//! Some functions here, such as `codegen_block` and `codegen_expr`, return a value --
//! the result of the codegen to LLVM -- while others, such as `codegen_fn`
//! and `mono_item`, are called only for the side effect of adding a
//! particular definition to the LLVM IR output we're producing.
//!
//! Hopefully useful general knowledge about codegen:
//!
//! * There's no way to find out the `Ty` type of a `Value`. Doing so
//! would be "trying to get the eggs out of an omelette" (credit:
//! pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
//! but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
//! int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.

use crate::back::write::{
compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,9 +760,9 @@ pub struct Pat<'hir> {
pub default_binding_modes: bool,
}

impl Pat<'_> {
impl<'hir> Pat<'hir> {
// FIXME(#19596) this is a workaround, but there should be a better way
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) -> bool {
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
if !it(self) {
return false;
}
Expand All @@ -785,12 +785,12 @@ impl Pat<'_> {
/// Note that when visiting e.g. `Tuple(ps)`,
/// if visiting `ps[0]` returns `false`,
/// then `ps[1]` will not be visited.
pub fn walk_short(&self, mut it: impl FnMut(&Pat<'_>) -> bool) -> bool {
pub fn walk_short(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) -> bool {
self.walk_short_(&mut it)
}

// FIXME(#19596) this is a workaround, but there should be a better way
fn walk_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) {
fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
if !it(self) {
return;
}
Expand All @@ -810,7 +810,7 @@ impl Pat<'_> {
/// Walk the pattern in left-to-right order.
///
/// If `it(pat)` returns `false`, the children are not visited.
pub fn walk(&self, mut it: impl FnMut(&Pat<'_>) -> bool) {
pub fn walk(&self, mut it: impl FnMut(&Pat<'hir>) -> bool) {
self.walk_(&mut it)
}

Expand Down
52 changes: 46 additions & 6 deletions compiler/rustc_typeck/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
use rustc_hir::{HirId, Node};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::util::IntTypeExt;
Expand All @@ -22,7 +22,6 @@ use super::{bad_placeholder_type, is_suggestable_infer_ty};
/// This should be called using the query `tcx.opt_const_param_of`.
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
use hir::*;

let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
Expand Down Expand Up @@ -62,9 +61,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
}

Node::Ty(&Ty { kind: TyKind::Path(_), .. })
| Node::Expr(&Expr { kind: ExprKind::Struct(..), .. })
| Node::Expr(&Expr { kind: ExprKind::Path(_), .. })
| Node::TraitRef(..) => {
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
| Node::TraitRef(..)
| Node::Pat(_) => {
let path = match parent_node {
Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
Expand All @@ -79,6 +78,20 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
let _tables = tcx.typeck(body_owner);
&*path
}
Node::Pat(pat) => {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
&format!(
"unable to find const parent for {} in pat {:?}",
hir_id, pat
),
);
return None;
}
}
_ => {
tcx.sess.delay_span_bug(
tcx.def_span(def_id),
Expand All @@ -91,7 +104,6 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.

let (arg_index, segment) = path
.segments
.iter()
Expand Down Expand Up @@ -144,6 +156,34 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
}
}

fn get_path_containing_arg_in_pat<'hir>(
pat: &'hir hir::Pat<'hir>,
arg_id: HirId,
) -> Option<&'hir hir::Path<'hir>> {
use hir::*;

let is_arg_in_path = |p: &hir::Path<'_>| {
p.segments
.iter()
.filter_map(|seg| seg.args)
.flat_map(|args| args.args)
.any(|arg| arg.id() == arg_id)
};
let mut arg_path = None;
pat.walk(|pat| match pat.kind {
PatKind::Struct(QPath::Resolved(_, path), _, _)
| PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
| PatKind::Path(QPath::Resolved(_, path))
if is_arg_in_path(path) =>
{
arg_path = Some(path);
false
}
_ => true,
});
arg_path
}

pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let def_id = def_id.expect_local();
use rustc_hir::*;
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ impl Merge for TomlConfig {
*x = Some(new);
}
}
};
}
do_merge(&mut self.build, build);
do_merge(&mut self.install, install);
do_merge(&mut self.llvm, llvm);
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/inline_local/trait-vis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ mod asdf {

// @has trait_vis/struct.SomeStruct.html
// @has - '//code' 'impl ThisTrait for SomeStruct'
// !@has - '//code' 'impl PrivateTrait for SomeStruct'
// @!has - '//code' 'impl PrivateTrait for SomeStruct'
pub use asdf::SomeStruct;
2 changes: 1 addition & 1 deletion src/test/rustdoc/issue-74083.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ impl Foo {
}

// @has issue_74083/struct.Bar.html
// !@has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
// @!has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
pub struct Bar {
foo: Foo,
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/remove-url-from-headings.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![crate_name = "foo"]

// @has foo/fn.foo.html
// !@has - '//a[@href="http://a.a"]'
// @!has - '//a[@href="http://a.a"]'
// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
// @has - '//a[@href="#another-one-urg"]' 'Another one urg'

Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/const-generics/arg-in-pat-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// check-pass
enum ConstGenericEnum<const N: usize> {
Foo([i32; N]),
Bar,
}

fn foo<const N: usize>(val: &ConstGenericEnum<N>) {
if let ConstGenericEnum::<N>::Foo(field, ..) = val {}
}

fn bar<const N: usize>(val: &ConstGenericEnum<N>) {
match val {
ConstGenericEnum::<N>::Foo(field, ..) => (),
ConstGenericEnum::<N>::Bar => (),
}
}

fn main() {
match ConstGenericEnum::Bar {
ConstGenericEnum::<3>::Foo(field, ..) => (),
ConstGenericEnum::<3>::Bar => (),
}
}
10 changes: 10 additions & 0 deletions src/test/ui/const-generics/arg-in-pat-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// check-pass
enum Generic<const N: usize> {
Variant,
}

fn main() {
match todo!() {
Generic::<0usize>::Variant => todo!()
}
}
43 changes: 43 additions & 0 deletions src/test/ui/const-generics/arg-in-pat-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// check-pass
struct Foo<const N: usize>;

fn bindingp() {
match Foo {
mut x @ Foo::<3> => {
let ref mut _x @ Foo::<3> = x;
}
}
}

struct Bar<const N: usize> {
field: Foo<N>,
}

fn structp() {
match todo!() {
Bar::<3> {
field: Foo::<3>,
} => (),
}
}

struct Baz<const N: usize>(Foo<N>);

fn tuplestructp() {
match Baz(Foo) {
Baz::<3>(Foo::<3>) => (),
}
}

impl<const N: usize> Baz<N> {
const ASSOC: usize = 3;
}

fn pathp() {
match 3 {
Baz::<3>::ASSOC => (),
_ => (),
}
}

fn main() {}
Loading