Auto merge of #73563 - Manishearth:rollup-oowgwwm, r=Manishearth

Rollup of 9 pull requests

Successful merges:

 - #72456 (Try to suggest dereferences on trait selection failed)
 - #72788 (Projection bound validation)
 - #72790 (core/time: Add Duration methods for zero)
 - #73227 (Allow multiple `asm!` options groups and report an error on duplicate options)
 - #73287 (lint: normalize projections using opaque types)
 - #73291 (Pre-compute `LocalDefId` <-> `HirId` mappings and remove `NodeId` <-> `HirId` conversion APIs)
 - #73378 (Remove use of specialization from librustc_arena)
 - #73411 (Update bootstrap to rustc 1.45.0-beta.2 (1dc0f6d8e 2020-06-15))
 - #73443 (ci: allow gating GHA on everything but macOS)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-06-20 22:53:46 +00:00
commit 7058471ade
136 changed files with 2870 additions and 1001 deletions

View File

@ -369,35 +369,6 @@ jobs:
env:
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
os: ubuntu-latest-xl
- name: dist-x86_64-apple
env:
SCRIPT: "./x.py dist"
RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
DIST_REQUIRE_ALL_TOOLS: 1
os: macos-latest
- name: dist-x86_64-apple-alt
env:
SCRIPT: "./x.py dist"
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
os: macos-latest
- name: x86_64-apple
env:
SCRIPT: "./x.py test"
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.8
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
os: macos-latest
- name: x86_64-msvc-1
env:
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
@ -580,6 +551,135 @@ jobs:
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
auto-fallible:
name: auto-fallible
env:
CI_JOB_NAME: "${{ matrix.name }}"
SCCACHE_BUCKET: rust-lang-gha-caches
DEPLOY_BUCKET: rust-lang-gha
TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues"
TOOLSTATE_PUBLISH: 1
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
CACHE_DOMAIN: ci-caches-gha.rust-lang.org
if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
strategy:
matrix:
include:
- name: dist-x86_64-apple
env:
SCRIPT: "./x.py dist"
RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
DIST_REQUIRE_ALL_TOOLS: 1
os: macos-latest
- name: dist-x86_64-apple-alt
env:
SCRIPT: "./x.py dist"
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
os: macos-latest
- name: x86_64-apple
env:
SCRIPT: "./x.py test"
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.8
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
os: macos-latest
timeout-minutes: 600
runs-on: "${{ matrix.os }}"
steps:
- name: disable git crlf conversion
run: git config --global core.autocrlf false
shell: bash
- name: checkout the source code
uses: actions/checkout@v1
with:
fetch-depth: 2
- name: configure GitHub Actions to kill the build when outdated
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
with:
github_token: "${{ secrets.github_token }}"
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
- name: add extra environment variables
run: src/ci/scripts/setup-environment.sh
env:
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
if: success() && !env.SKIP_JOB
- name: decide whether to skip this job
run: src/ci/scripts/should-skip-this.sh
if: success() && !env.SKIP_JOB
- name: collect CPU statistics
run: src/ci/scripts/collect-cpu-stats.sh
if: success() && !env.SKIP_JOB
- name: show the current environment
run: src/ci/scripts/dump-environment.sh
if: success() && !env.SKIP_JOB
- name: install awscli
run: src/ci/scripts/install-awscli.sh
if: success() && !env.SKIP_JOB
- name: install sccache
run: src/ci/scripts/install-sccache.sh
if: success() && !env.SKIP_JOB
- name: install clang
run: src/ci/scripts/install-clang.sh
if: success() && !env.SKIP_JOB
- name: install WIX
run: src/ci/scripts/install-wix.sh
if: success() && !env.SKIP_JOB
- name: install InnoSetup
run: src/ci/scripts/install-innosetup.sh
if: success() && !env.SKIP_JOB
- name: ensure the build happens on a partition with enough space
run: src/ci/scripts/symlink-build-dir.sh
if: success() && !env.SKIP_JOB
- name: disable git crlf conversion
run: src/ci/scripts/disable-git-crlf-conversion.sh
if: success() && !env.SKIP_JOB
- name: install MSYS2
run: src/ci/scripts/install-msys2.sh
if: success() && !env.SKIP_JOB
- name: install MinGW
run: src/ci/scripts/install-mingw.sh
if: success() && !env.SKIP_JOB
- name: install ninja
run: src/ci/scripts/install-ninja.sh
if: success() && !env.SKIP_JOB
- name: enable ipv6 on Docker
run: src/ci/scripts/enable-docker-ipv6.sh
if: success() && !env.SKIP_JOB
- name: disable git crlf conversion
run: src/ci/scripts/disable-git-crlf-conversion.sh
if: success() && !env.SKIP_JOB
- name: checkout submodules
run: src/ci/scripts/checkout-submodules.sh
if: success() && !env.SKIP_JOB
- name: ensure line endings are correct
run: src/ci/scripts/verify-line-endings.sh
if: success() && !env.SKIP_JOB
- name: run the build
run: src/ci/scripts/run-build-from-ci.sh
env:
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
if: success() && !env.SKIP_JOB
- name: upload artifacts to S3
run: src/ci/scripts/upload-artifacts.sh
env:
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
master:
name: master
runs-on: ubuntu-latest

View File

@ -414,42 +414,6 @@ jobs:
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
<<: *job-linux-xl
####################
# macOS Builders #
####################
- name: dist-x86_64-apple
env:
SCRIPT: ./x.py dist
RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-macos-xl
- name: dist-x86_64-apple-alt
env:
SCRIPT: ./x.py dist
RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
<<: *job-macos-xl
- name: x86_64-apple
env:
SCRIPT: ./x.py test
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.8
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
<<: *job-macos-xl
######################
# Windows Builders #
######################
@ -595,6 +559,51 @@ jobs:
SCRIPT: python x.py dist
<<: *job-windows-xl
auto-fallible:
<<: *base-ci-job
name: auto-fallible
env:
<<: [*shared-ci-variables, *prod-variables]
if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'
strategy:
matrix:
include:
####################
# macOS Builders #
####################
- name: dist-x86_64-apple
env:
SCRIPT: ./x.py dist
RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-macos-xl
- name: dist-x86_64-apple-alt
env:
SCRIPT: ./x.py dist
RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
<<: *job-macos-xl
- name: x86_64-apple
env:
SCRIPT: ./x.py test
RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.8
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
<<: *job-macos-xl
master:
name: master
runs-on: ubuntu-latest

View File

@ -1155,6 +1155,7 @@ impl<T: Deref, E> Result<T, E> {
/// # Examples
///
/// ```
/// #![feature(inner_deref)]
/// let x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&str, &u32> = Ok("hello");
/// assert_eq!(x.as_deref(), y);
@ -1189,12 +1190,15 @@ impl<T: DerefMut, E> Result<T, E> {
/// # Examples
///
/// ```
/// #![feature(inner_deref)]
/// let mut s = "HELLO".to_string();
/// let mut x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&mut str, &mut u32> = Ok("HELLO");
/// let y: Result<&mut str, &mut u32> = Ok(&mut s);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
///
/// let mut i = 42;
/// let mut x: Result<String, u32> = Err(42);
/// let y: Result<&mut str, &mut u32> = Err(&42);
/// let y: Result<&mut str, &mut u32> = Err(&mut i);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
/// ```
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {

View File

@ -31,7 +31,7 @@ const MICROS_PER_SEC: u64 = 1_000_000;
/// the number of nanoseconds.
///
/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
/// [`ops`] traits.
/// [`ops`] traits. It implements `Default` by returning a zero-length `Duration`.
///
/// [`Add`]: ../../std/ops/trait.Add.html
/// [`Sub`]: ../../std/ops/trait.Sub.html
@ -138,6 +138,24 @@ impl Duration {
Duration { secs, nanos }
}
/// Creates a new `Duration` that spans no time.
///
/// # Examples
///
/// ```
/// #![feature(duration_zero)]
/// use std::time::Duration;
///
/// let duration = Duration::zero();
/// assert!(duration.is_zero());
/// assert_eq!(duration.as_nanos(), 0);
/// ```
#[unstable(feature = "duration_zero", issue = "73544")]
#[inline]
pub const fn zero() -> Duration {
Duration { secs: 0, nanos: 0 }
}
/// Creates a new `Duration` from the specified number of whole seconds.
///
/// # Examples
@ -223,6 +241,29 @@ impl Duration {
}
}
/// Returns true if this `Duration` spans no time.
///
/// # Examples
///
/// ```
/// #![feature(duration_zero)]
/// use std::time::Duration;
///
/// assert!(Duration::zero().is_zero());
/// assert!(Duration::new(0, 0).is_zero());
/// assert!(Duration::from_nanos(0).is_zero());
/// assert!(Duration::from_secs(0).is_zero());
///
/// assert!(!Duration::new(1, 1).is_zero());
/// assert!(!Duration::from_nanos(1).is_zero());
/// assert!(!Duration::from_secs(1).is_zero());
/// ```
#[unstable(feature = "duration_zero", issue = "73544")]
#[inline]
pub const fn is_zero(&self) -> bool {
self.secs == 0 && self.nanos == 0
}
/// Returns the number of _whole_ seconds contained by this `Duration`.
///
/// The returned value does not include the fractional (nanosecond) part of the

View File

@ -611,7 +611,11 @@ macro_rules! which_arena_for_type {
#[macro_export]
macro_rules! declare_arena {
([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
// This macro has to take the same input as
// `impl_arena_allocatable_decoders` which requires a second version of
// each type. We ignore that type until we can fix
// `impl_arena_allocatable_decoders`.
([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
pub dropless: $crate::DroplessArena,
@ -619,39 +623,56 @@ macro_rules! declare_arena {
$($name: $crate::arena_for_type!($a[$ty]),)*
}
#[marker]
pub trait ArenaAllocatable<'tcx> {}
impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}
unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
/// Returns a specific arena to allocate from.
/// If `None` is returned, the `DropArena` will be used.
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
fn allocate_from_iter<'a>(
arena: &'a Arena<'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'a mut [Self];
}
unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
#[inline]
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
panic!()
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
arena.dropless.alloc(self)
}
#[inline]
fn allocate_from_iter<'a>(
arena: &'a Arena<'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'a mut [Self] {
arena.dropless.alloc_from_iter(iter)
}
}
}
$(
#[allow(unused_lifetimes)]
impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
#[inline]
fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
// SAFETY: We only implement `ArenaAllocatable<$tcx>` for
// `$ty`, so `$ty` and Self are the same type
unsafe {
::std::mem::transmute::<
Option<&'a $crate::TypedArena<$ty>>,
Option<&'a $crate::TypedArena<Self>>,
>(
$crate::which_arena_for_type!($a[&_arena.$name])
)
fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
if !::std::mem::needs_drop::<Self>() {
return arena.dropless.alloc(self);
}
match $crate::which_arena_for_type!($a[&arena.$name]) {
::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
ty_arena.alloc(self)
}
::std::option::Option::None => unsafe { arena.drop.alloc(self) },
}
}
#[inline]
fn allocate_from_iter<'a>(
arena: &'a Arena<$tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'a mut [Self] {
if !::std::mem::needs_drop::<Self>() {
return arena.dropless.alloc_from_iter(iter);
}
match $crate::which_arena_for_type!($a[&arena.$name]) {
::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
ty_arena.alloc_from_iter(iter)
}
::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
}
}
}
@ -659,14 +680,8 @@ macro_rules! declare_arena {
impl<'tcx> Arena<'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
if !::std::mem::needs_drop::<T>() {
return self.dropless.alloc(value);
}
match <T as ArenaField<'tcx>>::arena(self) {
::std::option::Option::Some(arena) => arena.alloc(value),
::std::option::Option::None => unsafe { self.drop.alloc(value) },
}
pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
value.allocate_on(self)
}
#[inline]
@ -677,17 +692,11 @@ macro_rules! declare_arena {
self.dropless.alloc_slice(value)
}
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
&'a self,
iter: impl ::std::iter::IntoIterator<Item = T>,
) -> &'a mut [T] {
if !::std::mem::needs_drop::<T>() {
return self.dropless.alloc_from_iter(iter);
}
match <T as ArenaField<'tcx>>::arena(self) {
::std::option::Option::Some(arena) => arena.alloc_from_iter(iter),
::std::option::Option::None => unsafe { self.drop.alloc_from_iter(iter) },
}
T::allocate_from_iter(self, iter)
}
}
}

View File

@ -32,8 +32,6 @@
#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)]
#![feature(marker_trait_attr)]
#![feature(min_specialization)]
#![feature(or_patterns)]
#![recursion_limit = "256"]
@ -205,6 +203,8 @@ pub trait Resolver {
fn lint_buffer(&mut self) -> &mut LintBuffer;
fn next_node_id(&mut self) -> NodeId;
fn trait_map(&self) -> &NodeMap<Vec<hir::TraitCandidate>>;
}
type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream;
@ -557,6 +557,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let proc_macros =
c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
let trait_map = self
.resolver
.trait_map()
.iter()
.map(|(&k, v)| (self.node_id_to_hir_id[k].unwrap(), v.clone()))
.collect();
self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id);
hir::Crate {
@ -571,6 +578,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
trait_impls: self.trait_impls,
modules: self.modules,
proc_macros,
trait_map,
}
}

View File

@ -16,7 +16,7 @@ struct AsmArgs {
named_args: FxHashMap<Symbol, usize>,
reg_args: FxHashSet<usize>,
options: ast::InlineAsmOptions,
options_span: Option<Span>,
options_spans: Vec<Span>,
}
fn parse_args<'a>(
@ -59,7 +59,7 @@ fn parse_args<'a>(
named_args: FxHashMap::default(),
reg_args: FxHashSet::default(),
options: ast::InlineAsmOptions::empty(),
options_span: None,
options_spans: vec![],
};
let mut allow_templates = true;
@ -174,9 +174,9 @@ fn parse_args<'a>(
// Validate the order of named, positional & explicit register operands and options. We do
// this at the end once we have the full span of the argument available.
if let Some(options_span) = args.options_span {
if !args.options_spans.is_empty() {
ecx.struct_span_err(span, "arguments are not allowed after options")
.span_label(options_span, "previous options")
.span_labels(args.options_spans.clone(), "previous options")
.span_label(span, "argument")
.emit();
}
@ -227,23 +227,23 @@ fn parse_args<'a>(
if args.options.contains(ast::InlineAsmOptions::NOMEM)
&& args.options.contains(ast::InlineAsmOptions::READONLY)
{
let span = args.options_span.unwrap();
ecx.struct_span_err(span, "the `nomem` and `readonly` options are mutually exclusive")
let spans = args.options_spans.clone();
ecx.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive")
.emit();
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& args.options.contains(ast::InlineAsmOptions::NORETURN)
{
let span = args.options_span.unwrap();
ecx.struct_span_err(span, "the `pure` and `noreturn` options are mutually exclusive")
let spans = args.options_spans.clone();
ecx.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive")
.emit();
}
if args.options.contains(ast::InlineAsmOptions::PURE)
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
{
let span = args.options_span.unwrap();
let spans = args.options_spans.clone();
ecx.struct_span_err(
span,
spans,
"the `pure` option must be combined with either `nomem` or `readonly`",
)
.emit();
@ -267,7 +267,7 @@ fn parse_args<'a>(
}
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
ecx.struct_span_err(
args.options_span.unwrap(),
args.options_spans.clone(),
"asm with `pure` option must have at least one output",
)
.emit();
@ -283,6 +283,50 @@ fn parse_args<'a>(
Ok(args)
}
/// Report a duplicate option error.
///
/// This function must be called immediately after the option token is parsed.
/// Otherwise, the suggestion will be incorrect.
fn err_duplicate_option<'a>(p: &mut Parser<'a>, symbol: Symbol, span: Span) {
let mut err = p
.sess
.span_diagnostic
.struct_span_err(span, &format!("the `{}` option was already provided", symbol));
err.span_label(span, "this option was already provided");
// Tool-only output
let mut full_span = span;
if p.token.kind == token::Comma {
full_span = full_span.to(p.token.span);
}
err.tool_only_span_suggestion(
full_span,
"remove this option",
String::new(),
Applicability::MachineApplicable,
);
err.emit();
}
/// Try to set the provided option in the provided `AsmArgs`.
/// If it is already set, report a duplicate option error.
///
/// This function must be called immediately after the option token is parsed.
/// Otherwise, the error will not point to the correct spot.
fn try_set_option<'a>(
p: &mut Parser<'a>,
args: &mut AsmArgs,
symbol: Symbol,
option: ast::InlineAsmOptions,
) {
if !args.options.contains(option) {
args.options |= option;
} else {
err_duplicate_option(p, symbol, p.prev_token.span);
}
}
fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), DiagnosticBuilder<'a>> {
let span_start = p.prev_token.span;
@ -290,20 +334,20 @@ fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), Diagn
while !p.eat(&token::CloseDelim(token::DelimToken::Paren)) {
if p.eat(&token::Ident(sym::pure, false)) {
args.options |= ast::InlineAsmOptions::PURE;
try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
} else if p.eat(&token::Ident(sym::nomem, false)) {
args.options |= ast::InlineAsmOptions::NOMEM;
try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
} else if p.eat(&token::Ident(sym::readonly, false)) {
args.options |= ast::InlineAsmOptions::READONLY;
try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
} else if p.eat(&token::Ident(sym::preserves_flags, false)) {
args.options |= ast::InlineAsmOptions::PRESERVES_FLAGS;
try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
} else if p.eat(&token::Ident(sym::noreturn, false)) {
args.options |= ast::InlineAsmOptions::NORETURN;
try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
} else if p.eat(&token::Ident(sym::nostack, false)) {
args.options |= ast::InlineAsmOptions::NOSTACK;
try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
} else {
p.expect(&token::Ident(sym::att_syntax, false))?;
args.options |= ast::InlineAsmOptions::ATT_SYNTAX;
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
}
// Allow trailing commas
@ -314,14 +358,7 @@ fn parse_options<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> Result<(), Diagn
}
let new_span = span_start.to(p.prev_token.span);
if let Some(options_span) = args.options_span {
p.struct_span_err(new_span, "asm options cannot be specified multiple times")
.span_label(options_span, "previously here")
.span_label(new_span, "duplicate options")
.emit();
} else {
args.options_span = Some(new_span);
}
args.options_spans.push(new_span);
Ok(())
}

View File

@ -81,14 +81,13 @@ pub struct Definitions {
def_id_to_span: IndexVec<LocalDefId, Span>,
// FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId`
// and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners.
node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
pub(super) node_id_to_hir_id: IndexVec<ast::NodeId, Option<hir::HirId>>,
/// The reverse mapping of `node_id_to_hir_id`.
pub(super) hir_id_to_node_id: FxHashMap<hir::HirId, ast::NodeId>,
// FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners.
pub(super) def_id_to_hir_id: IndexVec<LocalDefId, Option<hir::HirId>>,
/// The reverse mapping of `def_id_to_hir_id`.
pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>,
/// If `ExpnId` is an ID of some macro expansion,
/// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
@ -327,9 +326,7 @@ impl Definitions {
#[inline]
pub fn local_def_id(&self, node: ast::NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| {
panic!("no entry for node id: `{:?}` / `{:?}`", node, self.opt_node_id_to_hir_id(node))
})
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
}
#[inline]
@ -337,37 +334,19 @@ impl Definitions {
self.local_def_id_to_hir_id(def_id)
}
#[inline]
pub fn hir_id_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId {
self.hir_id_to_node_id[&hir_id]
}
#[inline]
pub fn node_id_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
self.node_id_to_hir_id[node_id].unwrap()
}
#[inline]
pub fn opt_node_id_to_hir_id(&self, node_id: ast::NodeId) -> Option<hir::HirId> {
self.node_id_to_hir_id[node_id]
}
#[inline]
pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
let node_id = self.def_id_to_node_id[id];
self.node_id_to_hir_id[node_id].unwrap()
self.def_id_to_hir_id[id].unwrap()
}
#[inline]
pub fn opt_local_def_id_to_hir_id(&self, id: LocalDefId) -> Option<hir::HirId> {
let node_id = self.def_id_to_node_id[id];
self.node_id_to_hir_id[node_id]
self.def_id_to_hir_id[id]
}
#[inline]
pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefId> {
let node_id = self.hir_id_to_node_id(hir_id);
self.opt_local_def_id(node_id)
self.hir_id_to_def_id.get(&hir_id).copied()
}
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
@ -477,16 +456,24 @@ impl Definitions {
mapping: IndexVec<ast::NodeId, Option<hir::HirId>>,
) {
assert!(
self.node_id_to_hir_id.is_empty(),
"trying to initialize `NodeId` -> `HirId` mapping twice"
self.def_id_to_hir_id.is_empty(),
"trying to initialize `LocalDefId` <-> `HirId` mappings twice"
);
self.node_id_to_hir_id = mapping;
// Build the reverse mapping of `node_id_to_hir_id`.
self.hir_id_to_node_id = self
.node_id_to_hir_id
.iter_enumerated()
.filter_map(|(node_id, &hir_id)| hir_id.map(|hir_id| (hir_id, node_id)))
self.def_id_to_hir_id = self
.def_id_to_node_id
.iter()
.map(|&node_id| mapping.get(node_id).and_then(|&hir_id| hir_id))
.collect();
// Build the reverse mapping of `def_id_to_hir_id`.
self.hir_id_to_def_id = mapping
.into_iter_enumerated()
.filter_map(|(node_id, hir_id)| {
hir_id.and_then(|hir_id| {
self.node_id_to_def_id.get(&node_id).map(|&def_id| (hir_id, def_id))
})
})
.collect();
}

View File

@ -639,6 +639,8 @@ pub struct Crate<'hir> {
/// A list of proc macro HirIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
pub proc_macros: Vec<HirId>,
pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
}
impl Crate<'hir> {
@ -2651,7 +2653,7 @@ pub type CaptureModeMap = NodeMap<CaptureBy>;
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
// has length > 0 if the trait is found through an chain of imports, starting with the
// import/use statement in the scope where the trait is used.
#[derive(Clone, Debug)]
#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_ids: SmallVec<[LocalDefId; 1]>,

View File

@ -1,9 +1,8 @@
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::{GenericKind, VerifyBound};
use crate::traits;
use rustc_data_structures::captures::Captures;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, Ty, TyCtxt};
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
@ -311,18 +310,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
fn region_bounds_declared_on_associated_item(
&self,
assoc_item_def_id: DefId,
) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
) -> impl Iterator<Item = ty::Region<'tcx>> {
let tcx = self.tcx;
let assoc_item = tcx.associated_item(assoc_item_def_id);
let trait_def_id = assoc_item.container.assert_trait();
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
self.collect_outlives_from_predicate_list(
move |ty| ty == identity_proj,
traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
)
.map(|b| b.1)
let predicates = tcx.projection_predicates(assoc_item_def_id);
predicates
.into_iter()
.filter_map(|p| p.to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars())
.map(|b| b.1)
}
/// Searches through a predicate list for a predicate `T: 'a`.

View File

@ -25,8 +25,6 @@ pub use self::project::{
Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
ProjectionCacheStorage, Reveal,
};
crate use self::util::elaborate_predicates;
pub use rustc_middle::traits::*;
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for

View File

@ -895,22 +895,33 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
struct ProhibitOpaqueTypes<'tcx> {
struct ProhibitOpaqueTypes<'a, 'tcx> {
cx: &'a LateContext<'a, 'tcx>,
ty: Option<Ty<'tcx>>,
};
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
if let ty::Opaque(..) = ty.kind {
self.ty = Some(ty);
true
} else {
ty.super_visit_with(self)
match ty.kind {
ty::Opaque(..) => {
self.ty = Some(ty);
true
}
// Consider opaque types within projections FFI-safe if they do not normalize
// to more opaque types.
ty::Projection(..) => {
let ty = self.cx.tcx.normalize_erasing_regions(self.cx.param_env, ty);
// If `ty` is a opaque type directly then `super_visit_with` won't invoke
// this function again.
if ty.has_opaque_types() { self.visit_ty(ty) } else { false }
}
_ => ty.super_visit_with(self),
}
}
}
let mut visitor = ProhibitOpaqueTypes { ty: None };
let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None };
ty.visit_with(&mut visitor);
if let Some(ty) = visitor.ty {
self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None);

View File

@ -117,6 +117,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
body_ids: _,
modules: _,
proc_macros: _,
trait_map: _,
} = *krate;
hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes)
@ -241,11 +242,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
// Make sure that the DepNode of some node coincides with the HirId
// owner of that node.
if cfg!(debug_assertions) {
let node_id = self.definitions.hir_id_to_node_id(hir_id);
assert_eq!(self.definitions.node_id_to_hir_id(node_id), hir_id);
if hir_id.owner != self.current_dep_node_owner {
let node_str = match self.definitions.opt_local_def_id(node_id) {
let node_str = match self.definitions.opt_hir_id_to_local_def_id(hir_id) {
Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(),
None => format!("{:?}", node),
};
@ -335,9 +333,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
debug!("visit_item: {:?}", i);
debug_assert_eq!(
i.hir_id.owner,
self.definitions
.opt_local_def_id(self.definitions.hir_id_to_node_id(i.hir_id))
.unwrap()
self.definitions.opt_hir_id_to_local_def_id(i.hir_id).unwrap()
);
self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| {
this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash);
@ -369,9 +365,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
debug_assert_eq!(
ti.hir_id.owner,
self.definitions
.opt_local_def_id(self.definitions.hir_id_to_node_id(ti.hir_id))
.unwrap()
self.definitions.opt_hir_id_to_local_def_id(ti.hir_id).unwrap()
);
self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| {
this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash);
@ -385,9 +379,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
debug_assert_eq!(
ii.hir_id.owner,
self.definitions
.opt_local_def_id(self.definitions.hir_id_to_node_id(ii.hir_id))
.unwrap()
self.definitions.opt_hir_id_to_local_def_id(ii.hir_id).unwrap()
);
self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| {
this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash);

View File

@ -36,7 +36,6 @@
#![feature(drain_filter)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![feature(marker_trait_attr)]
#![feature(extern_types)]
#![feature(nll)]
#![feature(option_expect_none)]

View File

@ -133,6 +133,23 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}
/// Returns the list of predicates that can be used for
/// `SelectionCandidate::ProjectionCandidate` and
/// `ProjectionTyCandidate::TraitDef`.
/// Specifically this is the bounds (equivalent to) those
/// written on the trait's type definition, or those
/// after the `impl` keyword
///
/// type X: Bound + 'lt
/// ^^^^^^^^^^^
/// impl Debug + Display
/// ^^^^^^^^^^^^^^^
///
/// `key` is the `DefId` of the associated type or opaque type.
query projection_predicates(key: DefId) -> &'tcx ty::List<ty::Predicate<'tcx>> {
desc { |tcx| "finding projection predicates for `{}`", tcx.def_path_str(key) }
}
query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLib>> {
desc { "looking up the native libraries of a linked crate" }
}

View File

@ -1101,9 +1101,9 @@ impl<'tcx> TyCtxt<'tcx> {
};
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (hir_id, v) in resolutions.trait_map.into_iter() {
for (hir_id, v) in krate.trait_map.iter() {
let map = trait_map.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, StableVec::new(v));
map.insert(hir_id.local_id, StableVec::new(v.to_vec()));
}
GlobalCtxt {

View File

@ -93,7 +93,6 @@ impl FlagComputation {
&ty::Bound(debruijn, _) => {
self.add_binder(debruijn);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
&ty::Placeholder(..) => {
@ -216,7 +215,6 @@ impl FlagComputation {
}
ty::ConstKind::Bound(debruijn, _) => {
self.add_binder(debruijn);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
ty::ConstKind::Param(_) => {
self.add_flags(TypeFlags::HAS_CT_PARAM);

View File

@ -121,7 +121,6 @@ pub struct ResolverOutputs {
pub definitions: rustc_hir::definitions::Definitions,
pub cstore: Box<CrateStoreDyn>,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub trait_map: FxHashMap<hir::HirId, Vec<hir::TraitCandidate>>,
pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
pub export_map: ExportMap<LocalDefId>,

View File

@ -1589,19 +1589,16 @@ impl RegionKind {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_INFER;
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
ty::RePlaceholder(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
ty::ReEarlyBound(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PARAM;
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
ty::ReFree { .. } => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;

View File

@ -333,6 +333,17 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
/// in a different item, with `target_substs` as the base for
/// the target impl/trait, with the source child-specific
/// parameters (e.g., method parameters) on top of that base.
///
/// For example given:
///
/// trait X<S> { fn f<T>(); }
/// impl<U> X<U> for U { fn f<V>() {} }
///
/// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait.
/// * If `source_ancestor` is the def_id of the trait.
/// * If `target_substs` is `[U]`, the substs for the impl.
/// * Then we will return `[U, T]`, the subst for `f` in the impl that
/// are needed for it to match the trait.
pub fn rebase_onto(
&self,
tcx: TyCtxt<'tcx>,

View File

@ -883,7 +883,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
})
.collect();
if !lifetimes.is_empty() {
self.trait_ref_hack = true;
let next_early_index = self.next_early_index();
let scope = Scope::Binder {
lifetimes,
@ -895,9 +894,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let result = self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
this.visit_ty(&bounded_ty);
this.trait_ref_hack = true;
walk_list!(this, visit_param_bound, bounds);
this.trait_ref_hack = false;
});
self.trait_ref_hack = false;
result
} else {
self.visit_ty(&bounded_ty);
@ -932,13 +932,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
let should_pop_missing_lt = self.is_trait_ref_fn_scope(trait_ref);
if !self.trait_ref_hack
let trait_ref_hack = take(&mut self.trait_ref_hack);
if !trait_ref_hack
|| trait_ref.bound_generic_params.iter().any(|param| match param.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
})
{
if self.trait_ref_hack {
if trait_ref_hack {
struct_span_err!(
self.tcx.sess,
trait_ref.span,
@ -968,10 +970,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
this.visit_trait_ref(&trait_ref.trait_ref);
})
});
} else {
self.visit_trait_ref(&trait_ref.trait_ref);
}
self.trait_ref_hack = trait_ref_hack;
if should_pop_missing_lt {
self.missing_named_lifetime_spots.pop();
}

View File

@ -1109,6 +1109,10 @@ impl rustc_ast_lowering::Resolver for Resolver<'_> {
fn next_node_id(&mut self) -> NodeId {
self.next_node_id()
}
fn trait_map(&self) -> &NodeMap<Vec<TraitCandidate>> {
&self.trait_map
}
}
impl<'a> Resolver<'a> {
@ -1284,11 +1288,6 @@ impl<'a> Resolver<'a> {
let definitions = self.definitions;
let extern_crate_map = self.extern_crate_map;
let export_map = self.export_map;
let trait_map = self
.trait_map
.into_iter()
.map(|(k, v)| (definitions.node_id_to_hir_id(k), v))
.collect();
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
let glob_map = self.glob_map;
@ -1297,7 +1296,6 @@ impl<'a> Resolver<'a> {
cstore: Box::new(self.crate_loader.into_cstore()),
extern_crate_map,
export_map,
trait_map,
glob_map,
maybe_unused_trait_imports,
maybe_unused_extern_crates,
@ -1315,11 +1313,6 @@ impl<'a> Resolver<'a> {
cstore: Box::new(self.cstore().clone()),
extern_crate_map: self.extern_crate_map.clone(),
export_map: self.export_map.clone(),
trait_map: self
.trait_map
.iter()
.map(|(&k, v)| (self.definitions.node_id_to_hir_id(k), v.clone()))
.collect(),
glob_map: self.glob_map.clone(),
maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(),
maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(),

View File

@ -0,0 +1,229 @@
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, TraitEngine};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
use rustc_middle::ty::{ToPredicate, TypeFoldable};
use rustc_session::DiagnosticMessageId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
#[derive(Copy, Clone, Debug)]
pub enum AutoderefKind {
Builtin,
Overloaded,
}
struct AutoderefSnapshot<'tcx> {
at_start: bool,
reached_recursion_limit: bool,
steps: Vec<(Ty<'tcx>, AutoderefKind)>,
cur_ty: Ty<'tcx>,
obligations: Vec<traits::PredicateObligation<'tcx>>,
}
pub struct Autoderef<'a, 'tcx> {
// Meta infos:
infcx: &'a InferCtxt<'a, 'tcx>,
span: Span,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
// Current state:
state: AutoderefSnapshot<'tcx>,
// Configurations:
include_raw_pointers: bool,
silence_errors: bool,
}
impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
type Item = (Ty<'tcx>, usize);
fn next(&mut self) -> Option<Self::Item> {
let tcx = self.infcx.tcx;
debug!("autoderef: steps={:?}, cur_ty={:?}", self.state.steps, self.state.cur_ty);
if self.state.at_start {
self.state.at_start = false;
debug!("autoderef stage #0 is {:?}", self.state.cur_ty);
return Some((self.state.cur_ty, 0));
}
// If we have reached the recursion limit, error gracefully.
if !tcx.sess.recursion_limit().value_within_limit(self.state.steps.len()) {
if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.state.cur_ty);
}
self.state.reached_recursion_limit = true;
return None;
}
if self.state.cur_ty.is_ty_var() {
return None;
}
// Otherwise, deref if type is derefable:
let (kind, new_ty) =
if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
(AutoderefKind::Builtin, mt.ty)
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
(AutoderefKind::Overloaded, ty)
} else {
return None;
};
if new_ty.references_error() {
return None;
}
self.state.steps.push((self.state.cur_ty, kind));
debug!(
"autoderef stage #{:?} is {:?} from {:?}",
self.step_count(),
new_ty,
(self.state.cur_ty, kind)
);
self.state.cur_ty = new_ty;
Some((self.state.cur_ty, self.step_count()))
}
}
impl<'a, 'tcx> Autoderef<'a, 'tcx> {
pub fn new(
infcx: &'a InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
span: Span,
base_ty: Ty<'tcx>,
) -> Autoderef<'a, 'tcx> {
Autoderef {
infcx,
span,
body_id,
param_env,
state: AutoderefSnapshot {
steps: vec![],
cur_ty: infcx.resolve_vars_if_possible(&base_ty),
obligations: vec![],
at_start: true,
reached_recursion_limit: false,
},
include_raw_pointers: false,
silence_errors: false,
}
}
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
debug!("overloaded_deref_ty({:?})", ty);
let tcx = self.infcx.tcx;
// <ty as Deref>
let trait_ref = TraitRef {
def_id: tcx.lang_items().deref_trait()?,
substs: tcx.mk_substs_trait(ty, &[]),
};
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let obligation = traits::Obligation::new(
cause.clone(),
self.param_env,
trait_ref.without_const().to_predicate(tcx),
);
if !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation");
return None;
}
let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot();
let normalized_ty = fulfillcx.normalize_projection_type(
&self.infcx,
self.param_env,
ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")),
cause,
);
if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
return None;
}
let obligations = fulfillcx.pending_obligations();
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);
Some(self.infcx.resolve_vars_if_possible(&normalized_ty))
}
/// Returns the final type we ended up with, which may be an inference
/// variable (we will resolve it first, if we want).
pub fn final_ty(&self, resolve: bool) -> Ty<'tcx> {
if resolve {
self.infcx.resolve_vars_if_possible(&self.state.cur_ty)
} else {
self.state.cur_ty
}
}
pub fn step_count(&self) -> usize {
self.state.steps.len()
}
pub fn into_obligations(self) -> Vec<traits::PredicateObligation<'tcx>> {
self.state.obligations
}
pub fn steps(&self) -> &[(Ty<'tcx>, AutoderefKind)] {
&self.state.steps
}
pub fn span(&self) -> Span {
self.span.clone()
}
pub fn reached_recursion_limit(&self) -> bool {
self.state.reached_recursion_limit
}
/// also dereference through raw pointer types
/// e.g., assuming ptr_to_Foo is the type `*const Foo`
/// fcx.autoderef(span, ptr_to_Foo) => [*const Foo]
/// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo]
pub fn include_raw_pointers(mut self) -> Self {
self.include_raw_pointers = true;
self
}
pub fn silence_errors(mut self) -> Self {
self.silence_errors = true;
self
}
}
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
// We've reached the recursion limit, error gracefully.
let suggested_limit = tcx.sess.recursion_limit() * 2;
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
if fresh {
struct_span_err!(
tcx.sess,
span,
E0055,
"reached the recursion limit while auto-dereferencing `{:?}`",
ty
)
.span_label(span, "deref recursion limit reached")
.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
suggested_limit, tcx.crate_name,
))
.emit();
}
}

View File

@ -28,6 +28,7 @@ extern crate log;
#[macro_use]
extern crate rustc_middle;
pub mod autoderef;
pub mod infer;
pub mod opaque_types;
pub mod traits;

View File

@ -402,6 +402,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err.span_label(enclosing_scope_span, s.as_str());
}
self.suggest_dereferences(&obligation, &mut err, &trait_ref, points_at_arg);
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);

View File

@ -3,6 +3,7 @@ use super::{
SelectionContext,
};
use crate::autoderef::Autoderef;
use crate::infer::InferCtxt;
use crate::traits::normalize_projection_type;
@ -13,11 +14,11 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
use rustc_middle::ty::TypeckTables;
use rustc_middle::ty::{
self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
TyCtxt, TypeFoldable, WithConstness,
};
use rustc_middle::ty::{TypeAndMut, TypeckTables};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{MultiSpan, Span, DUMMY_SP};
use std::fmt;
@ -48,6 +49,14 @@ pub trait InferCtxtExt<'tcx> {
err: &mut DiagnosticBuilder<'_>,
);
fn suggest_dereferences(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
points_at_arg: bool,
);
fn get_closure_name(
&self,
def_id: DefId,
@ -450,6 +459,62 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
/// When after several dereferencing, the reference satisfies the trait
/// binding. This function provides dereference suggestion for this
/// specific situation.
fn suggest_dereferences(
&self,
obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
points_at_arg: bool,
) {
// It only make sense when suggesting dereferences for arguments
if !points_at_arg {
return;
}
let param_env = obligation.param_env;
let body_id = obligation.cause.body_id;
let span = obligation.cause.span;
let real_trait_ref = match &obligation.cause.code {
ObligationCauseCode::ImplDerivedObligation(cause)
| ObligationCauseCode::DerivedObligation(cause)
| ObligationCauseCode::BuiltinDerivedObligation(cause) => &cause.parent_trait_ref,
_ => trait_ref,
};
let real_ty = match real_trait_ref.self_ty().no_bound_vars() {
Some(ty) => ty,
None => return,
};
if let ty::Ref(region, base_ty, mutbl) = real_ty.kind {
let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty);
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
// Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
let obligation =
self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_ref, ty);
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
}) {
if steps > 0 {
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) {
// Don't care about `&mut` because `DerefMut` is used less
// often and user will not expect autoderef happens.
if src.starts_with("&") && !src.starts_with("&mut ") {
let derefs = "*".repeat(steps);
err.span_suggestion(
span,
"consider adding dereference here",
format!("&{}{}", derefs, &src[1..]),
Applicability::MachineApplicable,
);
}
}
}
}
}
}
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
/// suggestion to borrow the initializer in order to use have a slice instead.
fn suggest_borrow_on_unsized_slice(

View File

@ -896,9 +896,12 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
let tcx = selcx.tcx();
// Check whether the self-type is itself a projection.
let (def_id, substs) = match obligation_trait_ref.self_ty().kind {
ty::Projection(ref data) => (data.trait_ref(tcx).def_id, data.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
// If so, extract what we know from the trait and try to come up with a good answer.
let bounds = match obligation_trait_ref.self_ty().kind {
ty::Projection(ref data) => {
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
}
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
// being a projected type, so induce an ambiguity.
@ -908,17 +911,13 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
_ => return,
};
// If so, extract what we know from the trait and try to come up with a good answer.
let trait_predicates = tcx.predicates_of(def_id);
let bounds = trait_predicates.instantiate(tcx, substs);
let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate);
assemble_candidates_from_predicates(
selcx,
obligation,
obligation_trait_ref,
candidate_set,
ProjectionTyCandidate::TraitDef,
bounds,
bounds.iter(),
)
}
@ -1484,6 +1483,12 @@ fn confirm_impl_candidate<'cx, 'tcx>(
);
return Progress { ty: tcx.ty_error(), obligations: nested };
}
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
//
// * `obligation.predicate.substs` is `[Vec<u32>, S]`
// * `substs` is `[u32]`
// * `substs` ends up as `[u32, S]`
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
let substs =
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);

View File

@ -1273,9 +1273,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
placeholder_trait_predicate,
);
let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind {
ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
let tcx = self.infcx.tcx;
let predicates = match placeholder_trait_predicate.trait_ref.self_ty().kind {
ty::Projection(ref data) => {
tcx.projection_predicates(data.item_def_id).subst(tcx, data.substs)
}
ty::Opaque(def_id, substs) => tcx.projection_predicates(def_id).subst(tcx, substs),
_ => {
span_bug!(
obligation.cause.span,
@ -1285,32 +1288,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
}
};
debug!(
"match_projection_obligation_against_definition_bounds: \
def_id={:?}, substs={:?}",
def_id, substs
);
let predicates_of = self.tcx().predicates_of(def_id);
let bounds = predicates_of.instantiate(self.tcx(), substs);
debug!(
"match_projection_obligation_against_definition_bounds: \
bounds={:?}",
bounds
);
let elaborated_predicates =
util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter());
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
self.infcx.probe(|_| {
self.match_projection(
obligation,
*bound,
placeholder_trait_predicate.trait_ref,
&placeholder_map,
snapshot,
)
})
let matching_bound = predicates.iter().find_map(|bound| {
if let ty::PredicateKind::Trait(bound, _) = bound.kind() {
let bound = bound.to_poly_trait_ref();
if self.infcx.probe(|_| {
self.match_projection(
obligation,
bound,
placeholder_trait_predicate.trait_ref,
&placeholder_map,
snapshot,
)
}) {
return Some(bound);
}
}
None
});
debug!(

View File

@ -1,8 +1,10 @@
use rustc_data_structures::svh::Svh;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_infer::traits::util;
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_session::CrateDisambiguator;
use rustc_span::symbol::Symbol;
@ -365,6 +367,133 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
fn_like.asyncness()
}
/// For associated types we allow bounds written on the associated type
/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
/// when desugared as bounds on the trait `where Self::X: Trait`.
///
/// Note that this filtering is done with the items identity substs to
/// simplify checking that these bounds are met in impls. This means that
/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
/// `hr-associated-type-bound-1.rs`.
fn associated_type_projection_predicates(
tcx: TyCtxt<'_>,
assoc_item_def_id: DefId,
) -> &'_ ty::List<ty::Predicate<'_>> {
let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
// We include predicates from the trait as well to handle
// `where Self::X: Trait`.
let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
let assoc_item_ty = ty::ProjectionTy {
item_def_id: assoc_item_def_id,
substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
};
let predicates = item_predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Projection(p) = tr.skip_binder().self_ty().kind {
if p == assoc_item_ty {
return Some(pred);
}
}
}
ty::PredicateKind::Projection(proj) => {
if let ty::Projection(p) = proj.skip_binder().projection_ty.self_ty().kind {
if p == assoc_item_ty {
return Some(pred);
}
}
}
ty::PredicateKind::TypeOutlives(outlives) => {
if let ty::Projection(p) = outlives.skip_binder().0.kind {
if p == assoc_item_ty {
return Some(pred);
}
}
}
_ => {}
}
None
});
let result = tcx.mk_predicates(predicates);
debug!(
"associated_type_projection_predicates({}) = {:?}",
tcx.def_path_str(assoc_item_def_id),
result
);
result
}
/// Opaque types don't have the same issues as associated types: the only
/// predicates on an opaque type (excluding those it inherits from its parent
/// item) should be of the form we're expecting.
fn opaque_type_projection_predicates(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> &'_ ty::List<ty::Predicate<'_>> {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let bounds = tcx.predicates_of(def_id);
let predicates =
util::elaborate_predicates(tcx, bounds.predicates.into_iter().map(|&(pred, _)| pred));
let filtered_predicates = predicates.filter_map(|obligation| {
let pred = obligation.predicate;
match pred.kind() {
ty::PredicateKind::Trait(tr, _) => {
if let ty::Opaque(opaque_def_id, opaque_substs) = tr.skip_binder().self_ty().kind {
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
ty::PredicateKind::Projection(proj) => {
if let ty::Opaque(opaque_def_id, opaque_substs) =
proj.skip_binder().projection_ty.self_ty().kind
{
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
}
}
ty::PredicateKind::TypeOutlives(outlives) => {
if let ty::Opaque(opaque_def_id, opaque_substs) = outlives.skip_binder().0.kind {
if opaque_def_id == def_id && opaque_substs == substs {
return Some(pred);
}
} else {
// These can come from elaborating other predicates
return None;
}
}
// These can come from elaborating other predicates
ty::PredicateKind::RegionOutlives(_) => return None,
_ => {}
}
tcx.sess.delay_span_bug(
obligation.cause.span(tcx),
&format!("unexpected predicate {:?} on opaque type", pred),
);
None
});
let result = tcx.mk_predicates(filtered_predicates);
debug!("opaque_type_projection_predicates({}) = {:?}", tcx.def_path_str(def_id), result);
result
}
fn projection_predicates(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
match tcx.def_kind(def_id) {
DefKind::AssocTy => associated_type_projection_predicates(tcx, def_id),
DefKind::OpaqueTy => opaque_type_projection_predicates(tcx, def_id),
k => bug!("projection_predicates called on {}", k.descr(def_id)),
}
}
pub fn provide(providers: &mut ty::query::Providers<'_>) {
*providers = ty::query::Providers {
asyncness,
@ -381,6 +510,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
projection_predicates,
..*providers
};
}

View File

@ -1,191 +1,46 @@
//! Some helper functions for `AutoDeref`
use super::method::MethodCallee;
use super::{FnCtxt, PlaceOp};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_infer::infer::{InferCtxt, InferOk};
use rustc_infer::infer::InferOk;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
use rustc_middle::ty::{ToPredicate, TypeFoldable};
use rustc_session::DiagnosticMessageId;
use rustc_span::symbol::Ident;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{self, TraitEngine};
use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
use std::iter;
#[derive(Copy, Clone, Debug)]
enum AutoderefKind {
Builtin,
Overloaded,
}
pub struct Autoderef<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
steps: Vec<(Ty<'tcx>, AutoderefKind)>,
cur_ty: Ty<'tcx>,
obligations: Vec<traits::PredicateObligation<'tcx>>,
at_start: bool,
include_raw_pointers: bool,
span: Span,
silence_errors: bool,
reached_recursion_limit: bool,
}
impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
type Item = (Ty<'tcx>, usize);
fn next(&mut self) -> Option<Self::Item> {
let tcx = self.infcx.tcx;
debug!("autoderef: steps={:?}, cur_ty={:?}", self.steps, self.cur_ty);
if self.at_start {
self.at_start = false;
debug!("autoderef stage #0 is {:?}", self.cur_ty);
return Some((self.cur_ty, 0));
}
if !tcx.sess.recursion_limit().value_within_limit(self.steps.len()) {
if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
}
self.reached_recursion_limit = true;
return None;
}
if self.cur_ty.is_ty_var() {
return None;
}
// Otherwise, deref if type is derefable:
let (kind, new_ty) = if let Some(mt) = self.cur_ty.builtin_deref(self.include_raw_pointers)
{
(AutoderefKind::Builtin, mt.ty)
} else {
let ty = self.overloaded_deref_ty(self.cur_ty)?;
(AutoderefKind::Overloaded, ty)
};
if new_ty.references_error() {
return None;
}
self.steps.push((self.cur_ty, kind));
debug!(
"autoderef stage #{:?} is {:?} from {:?}",
self.steps.len(),
new_ty,
(self.cur_ty, kind)
);
self.cur_ty = new_ty;
Some((self.cur_ty, self.steps.len()))
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
}
}
impl<'a, 'tcx> Autoderef<'a, 'tcx> {
pub fn new(
infcx: &'a InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
pub fn try_overloaded_deref(
&self,
span: Span,
base_ty: Ty<'tcx>,
) -> Autoderef<'a, 'tcx> {
Autoderef {
infcx,
body_id,
param_env,
steps: vec![],
cur_ty: infcx.resolve_vars_if_possible(&base_ty),
obligations: vec![],
at_start: true,
include_raw_pointers: false,
silence_errors: false,
reached_recursion_limit: false,
span,
}
}
fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
debug!("overloaded_deref_ty({:?})", ty);
let tcx = self.infcx.tcx;
// <ty as Deref>
let trait_ref = TraitRef {
def_id: tcx.lang_items().deref_trait()?,
substs: tcx.mk_substs_trait(ty, &[]),
};
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let obligation = traits::Obligation::new(
cause.clone(),
self.param_env,
trait_ref.without_const().to_predicate(tcx),
);
if !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation");
return None;
}
let mut fulfillcx = traits::FulfillmentContext::new_in_snapshot();
let normalized_ty = fulfillcx.normalize_projection_type(
&self.infcx,
self.param_env,
ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, Ident::from_str("Target")),
cause,
);
if let Err(e) = fulfillcx.select_where_possible(&self.infcx) {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", e);
return None;
}
let obligations = fulfillcx.pending_obligations();
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.obligations.extend(obligations);
Some(self.infcx.resolve_vars_if_possible(&normalized_ty))
}
/// Returns the final type, generating an error if it is an
/// unresolved inference variable.
pub fn unambiguous_final_ty(&self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
fcx.structurally_resolved_type(self.span, self.cur_ty)
}
/// Returns the final type we ended up with, which may well be an
/// inference variable (we will resolve it first, if possible).
pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> {
self.infcx.resolve_vars_if_possible(&self.cur_ty)
}
pub fn step_count(&self) -> usize {
self.steps.len()
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
}
/// Returns the adjustment steps.
pub fn adjust_steps(&self, fcx: &FnCtxt<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
fcx.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(fcx))
pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef))
}
pub fn adjust_steps_as_infer_ok(
&self,
fcx: &FnCtxt<'a, 'tcx>,
autoderef: &Autoderef<'a, 'tcx>,
) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
let mut obligations = vec![];
let targets = self.steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(self.cur_ty));
let steps: Vec<_> = self
.steps
let steps = autoderef.steps();
let targets =
steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
let steps: Vec<_> = steps
.iter()
.map(|&(source, kind)| {
if let AutoderefKind::Overloaded = kind {
fcx.try_overloaded_deref(self.span, source).and_then(
self.try_overloaded_deref(autoderef.span(), source).and_then(
|InferOk { value: method, obligations: o }| {
obligations.extend(o);
if let ty::Ref(region, _, mutbl) = method.sig.output().kind {
@ -205,67 +60,4 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
InferOk { obligations, value: steps }
}
/// also dereference through raw pointer types
/// e.g., assuming ptr_to_Foo is the type `*const Foo`
/// fcx.autoderef(span, ptr_to_Foo) => [*const Foo]
/// fcx.autoderef(span, ptr_to_Foo).include_raw_ptrs() => [*const Foo, Foo]
pub fn include_raw_pointers(mut self) -> Self {
self.include_raw_pointers = true;
self
}
pub fn silence_errors(mut self) -> Self {
self.silence_errors = true;
self
}
pub fn reached_recursion_limit(&self) -> bool {
self.reached_recursion_limit
}
pub fn finalize(self, fcx: &FnCtxt<'a, 'tcx>) {
fcx.register_predicates(self.into_obligations());
}
pub fn into_obligations(self) -> Vec<traits::PredicateObligation<'tcx>> {
self.obligations
}
}
pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) {
// We've reached the recursion limit, error gracefully.
let suggested_limit = tcx.sess.recursion_limit() * 2;
let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty);
let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg);
let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
if fresh {
struct_span_err!(
tcx.sess,
span,
E0055,
"reached the recursion limit while auto-dereferencing `{:?}`",
ty
)
.span_label(span, "deref recursion limit reached")
.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
suggested_limit, tcx.crate_name,
))
.emit();
}
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
}
pub fn try_overloaded_deref(
&self,
span: Span,
base_ty: Ty<'tcx>,
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
}
}

View File

@ -1,4 +1,3 @@
use super::autoderef::Autoderef;
use super::method::MethodCallee;
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
use crate::type_error_struct;
@ -17,6 +16,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
/// Checks that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
while result.is_none() && autoderef.next().is_some() {
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
}
autoderef.finalize(self);
self.register_predicates(autoderef.into_obligations());
let output = match result {
None => {
@ -106,7 +106,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
let adjusted_ty = autoderef.unambiguous_final_ty(self);
let adjusted_ty =
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
debug!(
"try_overloaded_call_step(call_expr={:?}, adjusted_ty={:?})",
call_expr, adjusted_ty
@ -115,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the callee is a bare function or a closure, then we're all set.
match adjusted_ty.kind {
ty::FnDef(..) | ty::FnPtr(_) => {
let adjustments = autoderef.adjust_steps(self);
let adjustments = self.adjust_steps(autoderef);
self.apply_adjustments(callee_expr, adjustments);
return Some(CallStep::Builtin(adjusted_ty));
}
@ -135,7 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&closure_sig,
)
.0;
let adjustments = autoderef.adjust_steps(self);
let adjustments = self.adjust_steps(autoderef);
self.record_deferred_call_resolution(
def_id,
DeferredCallResolution {
@ -176,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.try_overloaded_call_traits(call_expr, adjusted_ty, Some(arg_exprs))
.or_else(|| self.try_overloaded_call_traits(call_expr, adjusted_ty, None))
.map(|(autoref, method)| {
let mut adjustments = autoderef.adjust_steps(self);
let mut adjustments = self.adjust_steps(autoderef);
adjustments.extend(autoref);
self.apply_adjustments(callee_expr, adjustments);
CallStep::Overloaded(method)

View File

@ -409,7 +409,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
let InferOk { value: mut adjustments, obligations: o } =
autoderef.adjust_steps_as_infer_ok(self);
self.adjust_steps_as_infer_ok(&autoderef);
obligations.extend(o);
obligations.extend(autoderef.into_obligations());

View File

@ -4,15 +4,17 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit;
use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
use rustc_middle::ty;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use super::{potentially_plural_count, FnCtxt, Inherited};
use std::iter;
/// Checks that a method from an impl conforms to the signature of
/// the same method as declared in the trait.
@ -1057,13 +1059,15 @@ crate fn compare_ty_impl<'tcx>(
let _: Result<(), ErrorReported> = (|| {
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
compare_projection_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
})();
}
/// The equivalent of [compare_predicate_entailment], but for associated types
/// instead of associated functions.
fn compare_type_predicate_entailment(
fn compare_type_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
@ -1165,6 +1169,145 @@ fn compare_type_predicate_entailment(
})
}
/// Validate that `ProjectionCandidate`s created for this associated type will
/// be valid.
///
/// Usually given
///
/// trait X { type Y: Copy } impl X for T { type Y = S; }
///
/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
/// impl is well-formed we have to prove `S: Copy`.
///
/// For default associated types the normalization is not possible (the value
/// from the impl could be overridden). We also can't normalize generic
/// associated types (yet) because they contain bound parameters.
fn compare_projection_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ty: &ty::AssocItem,
impl_ty: &ty::AssocItem,
impl_ty_span: Span,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorReported> {
let have_gats = tcx.features().generic_associated_types;
if impl_ty.defaultness.is_final() && !have_gats {
// For "final", non-generic associate type implementations, we
// don't need this as described above.
return Ok(());
}
let param_env = tcx.param_env(impl_ty.def_id);
// Given
//
// impl<A, B> Foo<u32> for (A, B) {
// type Bar<C> =...
// }
//
// - `impl_substs` would be `[A, B, C]`
// - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from
// the *trait* with the generic associated type parameters.
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
let rebased_substs =
impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
let impl_ty_value = tcx.type_of(impl_ty.def_id);
// Map the predicate from the trait to the corresponding one for the impl.
// For example:
//
// trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
// impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
//
// For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
// function would translate and partially normalize
// `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
tcx.mk_substs(
iter::once(impl_ty_value.into())
.chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))),
)
};
tcx.infer_ctxt().enter(move |infcx| {
let inh = Inherited::new(infcx, impl_ty.def_id.expect_local());
let infcx = &inh.infcx;
let mut selcx = traits::SelectionContext::new(&infcx);
let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
let cause = ObligationCause::new(
impl_ty_span,
impl_ty_hir_id,
ObligationCauseCode::ItemObligation(trait_ty.def_id),
);
let predicates = tcx.projection_predicates(trait_ty.def_id);
debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
for predicate in predicates {
let concrete_ty_predicate = match predicate.kind() {
ty::PredicateKind::Trait(poly_tr, c) => poly_tr
.map_bound(|tr| {
let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
})
.with_constness(*c)
.to_predicate(tcx),
ty::PredicateKind::Projection(poly_projection) => poly_projection
.map_bound(|projection| {
let projection_substs =
translate_predicate_substs(projection.projection_ty.substs);
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
substs: projection_substs,
item_def_id: projection.projection_ty.item_def_id,
},
ty: projection.ty.subst(tcx, rebased_substs),
}
})
.to_predicate(tcx),
ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives
.map_bound(|outlives| {
ty::OutlivesPredicate(impl_ty_value, outlives.1.subst(tcx, rebased_substs))
})
.to_predicate(tcx),
_ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
};
let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
&mut selcx,
param_env,
normalize_cause.clone(),
&concrete_ty_predicate,
);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
inh.register_predicates(obligations);
inh.register_predicate(traits::Obligation::new(
cause.clone(),
param_env,
normalized_predicate,
));
}
// Check that all obligations are satisfied by the implementation's
// version.
if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
infcx.report_fulfillment_errors(errors, None, false);
return Err(ErrorReported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
Ok(())
})
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
match impl_item.kind {
ty::AssocKind::Const => "const",

View File

@ -1447,9 +1447,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// of error recovery.
self.write_field_index(expr.hir_id, index);
if field.vis.is_accessible_from(def_scope, self.tcx) {
let adjustments = autoderef.adjust_steps(self);
let adjustments = self.adjust_steps(&autoderef);
self.apply_adjustments(base, adjustments);
autoderef.finalize(self);
self.register_predicates(autoderef.into_obligations());
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span);
return field_ty;
@ -1462,9 +1462,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Ok(index) = fstr.parse::<usize>() {
if fstr == index.to_string() {
if let Some(field_ty) = tys.get(index) {
let adjustments = autoderef.adjust_steps(self);
let adjustments = self.adjust_steps(&autoderef);
self.apply_adjustments(base, adjustments);
autoderef.finalize(self);
self.register_predicates(autoderef.into_obligations());
self.write_field_index(expr.hir_id, index);
return field_ty.expect_ty();
@ -1475,7 +1475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => {}
}
}
autoderef.unambiguous_final_ty(self);
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
if let Some((did, field_ty)) = private_candidate {
self.ban_private_field_access(expr, expr_t, field, did);

View File

@ -144,9 +144,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
};
assert_eq!(n, pick.autoderefs);
let mut adjustments = autoderef.adjust_steps(self);
let mut adjustments = self.adjust_steps(&autoderef);
let mut target = autoderef.unambiguous_final_ty(self);
let mut target =
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
if let Some(mutbl) = pick.autoref {
let region = self.next_region_var(infer::Autoref(self.span));
@ -176,7 +177,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
assert!(pick.unsize.is_none());
}
autoderef.finalize(self);
self.register_predicates(autoderef.into_obligations());
// Write out the final adjustments.
self.apply_adjustments(self.self_expr, adjustments);

View File

@ -3,7 +3,6 @@ use super::MethodError;
use super::NoMatchData;
use super::{CandidateSource, ImplSource, TraitSource};
use crate::check::autoderef::{self, Autoderef};
use crate::check::FnCtxt;
use crate::hir::def::DefKind;
use crate::hir::def_id::DefId;
@ -30,6 +29,7 @@ use rustc_session::config::nightly_options;
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::autoderef::{self, Autoderef};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
use rustc_trait_selection::traits::query::method_autoderef::{
@ -477,7 +477,7 @@ fn method_autoderef_steps<'tcx>(
})
.collect();
let final_ty = autoderef.maybe_ambiguous_final_ty();
let final_ty = autoderef.final_ty(true);
let opt_bad_ty = match final_ty.kind {
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,

View File

@ -2281,7 +2281,7 @@ fn check_impl_items_against_trait<'tcx>(
&ty_trait_item,
impl_trait_ref,
opt_trait_span,
)
);
} else {
let mut err = struct_span_err!(
tcx.sess,

View File

@ -1,4 +1,3 @@
use crate::check::autoderef::Autoderef;
use crate::check::method::MethodCallee;
use crate::check::{FnCtxt, PlaceOp};
use rustc_hir as hir;
@ -9,6 +8,7 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::autoderef::Autoderef;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@ -57,7 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
while result.is_none() && autoderef.next().is_some() {
result = self.try_index_step(expr, base_expr, &autoderef, idx_ty);
}
autoderef.finalize(self);
self.register_predicates(autoderef.into_obligations());
result
}
@ -73,7 +73,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
autoderef: &Autoderef<'a, 'tcx>,
index_ty: Ty<'tcx>,
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
let adjusted_ty = autoderef.unambiguous_final_ty(self);
let adjusted_ty =
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
debug!(
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
index_ty={:?})",
@ -105,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("try_index_step: success, using overloaded indexing");
let method = self.register_infer_ok_obligations(ok);
let mut adjustments = autoderef.adjust_steps(self);
let mut adjustments = self.adjust_steps(autoderef);
if let ty::Ref(region, _, hir::Mutability::Not) = method.sig.inputs()[0].kind {
adjustments.push(Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(region, AutoBorrowMutability::Not)),

View File

@ -1118,7 +1118,7 @@ fn receiver_is_valid<'fcx, 'tcx>(
);
if can_eq_self(potential_self_ty) {
autoderef.finalize(fcx);
fcx.register_predicates(autoderef.into_obligations());
if let Some(mut err) =
fcx.demand_eqtype_with_origin(&cause, self_ty, potential_self_ty)

View File

@ -35,7 +35,7 @@ use rustc_middle::hir::map::Map;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
@ -1692,6 +1692,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
let mut is_trait = None;
let mut is_default_impl_trait = None;
let mut is_trait_associated_type = None;
let icx = ItemCtxt::new(tcx, def_id);
let constness = icx.default_constness_for_trait_bounds();
@ -1701,7 +1702,12 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
let mut predicates = UniquePredicates::new();
let ast_generics = match node {
Node::TraitItem(item) => &item.generics,
Node::TraitItem(item) => {
if let hir::TraitItemKind::Type(bounds, _) = item.kind {
is_trait_associated_type = Some((bounds, item.span));
}
&item.generics
}
Node::ImplItem(item) => &item.generics,
@ -1925,10 +1931,21 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
}
}
// Add predicates from associated type bounds.
if let Some((self_trait_ref, trait_items)) = is_trait {
// Add predicates from associated type bounds (`type X: Bound`)
if tcx.features().generic_associated_types {
// New behavior: bounds declared on associate type are predicates of that
// associated type. Not the default because it needs more testing.
if let Some((bounds, span)) = is_trait_associated_type {
let projection_ty =
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id));
predicates.extend(associated_item_bounds(tcx, def_id, bounds, projection_ty, span))
}
} else if let Some((self_trait_ref, trait_items)) = is_trait {
// Current behavior: bounds declared on associate type are predicates
// of its parent trait.
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
trait_associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
}))
}
@ -1958,7 +1975,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
result
}
fn associated_item_predicates(
fn trait_associated_item_predicates(
tcx: TyCtxt<'tcx>,
def_id: DefId,
self_trait_ref: ty::TraitRef<'tcx>,
@ -1971,92 +1988,40 @@ fn associated_item_predicates(
_ => return Vec::new(),
};
let is_gat = !tcx.generics_of(item_def_id).params.is_empty();
if !tcx.generics_of(item_def_id).params.is_empty() {
// For GATs the substs provided to the mk_projection call below are
// wrong. We should emit a feature gate error if we get here so skip
// this type.
tcx.sess.delay_span_bug(trait_item.span, "gats used without feature gate");
return Vec::new();
}
let mut had_error = false;
let mut unimplemented_error = |arg_kind: &str| {
if !had_error {
tcx.sess
.struct_span_err(
trait_item.span,
&format!("{}-generic associated types are not yet implemented", arg_kind),
)
.note(
"for more information, see issue #44265 \
<https://github.com/rust-lang/rust/issues/44265> for more information",
)
.emit();
had_error = true;
}
};
let mk_bound_param = |param: &ty::GenericParamDef, _: &_| {
match param.kind {
ty::GenericParamDefKind::Lifetime => tcx
.mk_region(ty::RegionKind::ReLateBound(
ty::INNERMOST,
ty::BoundRegion::BrNamed(param.def_id, param.name),
))
.into(),
// FIXME(generic_associated_types): Use bound types and constants
// once they are handled by the trait system.
ty::GenericParamDefKind::Type { .. } => {
unimplemented_error("type");
tcx.ty_error().into()
}
ty::GenericParamDefKind::Const => {
unimplemented_error("const");
tcx.const_error(tcx.type_of(param.def_id)).into()
}
}
};
let bound_substs = if is_gat {
// Given:
//
// trait X<'a, B, const C: usize> {
// type T<'d, E, const F: usize>: Default;
// }
//
// We need to create predicates on the trait:
//
// for<'d, E, const F: usize>
// <Self as X<'a, B, const C: usize>>::T<'d, E, const F: usize>: Sized + Default
//
// We substitute escaping bound parameters for the generic
// arguments to the associated type which are then bound by
// the `Binder` around the the predicate.
//
// FIXME(generic_associated_types): Currently only lifetimes are handled.
self_trait_ref.substs.extend_to(tcx, item_def_id.to_def_id(), mk_bound_param)
} else {
self_trait_ref.substs
};
let assoc_ty =
tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id).to_def_id(), bound_substs);
let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, def_id),
assoc_ty,
bounds,
SizedByDefault::Yes,
trait_item.span,
let assoc_ty = tcx.mk_projection(
tcx.hir().local_def_id(trait_item.hir_id).to_def_id(),
self_trait_ref.substs,
);
let predicates = bounds.predicates(tcx, assoc_ty);
associated_item_bounds(tcx, def_id, bounds, assoc_ty, trait_item.span)
}
if is_gat {
// We use shifts to get the regions that we're substituting to
// be bound by the binders in the `Predicate`s rather that
// escaping.
let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1);
let substituted = shifted_in.subst(tcx, bound_substs);
ty::fold::shift_out_vars(tcx, &substituted, 1)
} else {
predicates
}
fn associated_item_bounds(
tcx: TyCtxt<'tcx>,
def_id: DefId,
bounds: &'tcx [hir::GenericBound<'tcx>],
projection_ty: Ty<'tcx>,
span: Span,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let bounds = AstConv::compute_bounds(
&ItemCtxt::new(tcx, def_id),
projection_ty,
bounds,
SizedByDefault::Yes,
span,
);
let predicates = bounds.predicates(tcx, projection_ty);
predicates
}
/// Converts a specific `GenericBound` from the AST into a set of

View File

@ -12,7 +12,7 @@
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.(x+1).0` for Cargo where they were released on `date`.
date: 2020-06-03
date: 2020-06-16
rustc: beta
cargo: beta

View File

@ -0,0 +1,53 @@
// compile-flags: -O
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm)]
// CHECK-LABEL: @pure
// CHECK-NOT: asm
// CHECK: ret void
#[no_mangle]
pub unsafe fn pure(x: i32) {
let y: i32;
asm!("", out("ax") y, in("bx") x, options(pure), options(nomem));
}
pub static mut VAR: i32 = 0;
pub static mut DUMMY_OUTPUT: i32 = 0;
// CHECK-LABEL: @readonly
// CHECK: call i32 asm
// CHECK: ret i32 1
#[no_mangle]
pub unsafe fn readonly() -> i32 {
VAR = 1;
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
VAR
}
// CHECK-LABEL: @nomem
// CHECK-NOT: store
// CHECK: call i32 asm
// CHECK: store
// CHECK: ret i32 2
#[no_mangle]
pub unsafe fn nomem() -> i32 {
VAR = 1;
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(nomem));
VAR = 2;
VAR
}
// CHECK-LABEL: @not_nomem
// CHECK: store
// CHECK: call i32 asm
// CHECK: store
// CHECK: ret i32 2
#[no_mangle]
pub unsafe fn not_nomem() -> i32 {
VAR = 1;
asm!("", out("ax") DUMMY_OUTPUT, options(pure), options(readonly));
VAR = 2;
VAR
}

View File

@ -0,0 +1,26 @@
// only-x86_64
// run-rustfix
#![feature(asm)]
fn main() {
unsafe {
asm!("", options(nomem, ));
//~^ ERROR the `nomem` option was already provided
asm!("", options(att_syntax, ));
//~^ ERROR the `att_syntax` option was already provided
asm!("", options(nostack, att_syntax), options());
//~^ ERROR the `nostack` option was already provided
asm!("", options(nostack, ), options(), options());
//~^ ERROR the `nostack` option was already provided
//~| ERROR the `nostack` option was already provided
//~| ERROR the `nostack` option was already provided
asm!(
"",
options(nomem, noreturn),
options(att_syntax, ), //~ ERROR the `noreturn` option was already provided
options( nostack), //~ ERROR the `nomem` option was already provided
options(), //~ ERROR the `noreturn` option was already provided
);
}
}

View File

@ -0,0 +1,26 @@
// only-x86_64
// run-rustfix
#![feature(asm)]
fn main() {
unsafe {
asm!("", options(nomem, nomem));
//~^ ERROR the `nomem` option was already provided
asm!("", options(att_syntax, att_syntax));
//~^ ERROR the `att_syntax` option was already provided
asm!("", options(nostack, att_syntax), options(nostack));
//~^ ERROR the `nostack` option was already provided
asm!("", options(nostack, nostack), options(nostack), options(nostack));
//~^ ERROR the `nostack` option was already provided
//~| ERROR the `nostack` option was already provided
//~| ERROR the `nostack` option was already provided
asm!(
"",
options(nomem, noreturn),
options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
options(noreturn), //~ ERROR the `noreturn` option was already provided
);
}
}

View File

@ -0,0 +1,56 @@
error: the `nomem` option was already provided
--> $DIR/duplicate-options.rs:8:33
|
LL | asm!("", options(nomem, nomem));
| ^^^^^ this option was already provided
error: the `att_syntax` option was already provided
--> $DIR/duplicate-options.rs:10:38
|
LL | asm!("", options(att_syntax, att_syntax));
| ^^^^^^^^^^ this option was already provided
error: the `nostack` option was already provided
--> $DIR/duplicate-options.rs:12:56
|
LL | asm!("", options(nostack, att_syntax), options(nostack));
| ^^^^^^^ this option was already provided
error: the `nostack` option was already provided
--> $DIR/duplicate-options.rs:14:35
|
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
| ^^^^^^^ this option was already provided
error: the `nostack` option was already provided
--> $DIR/duplicate-options.rs:14:53
|
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
| ^^^^^^^ this option was already provided
error: the `nostack` option was already provided
--> $DIR/duplicate-options.rs:14:71
|
LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
| ^^^^^^^ this option was already provided
error: the `noreturn` option was already provided
--> $DIR/duplicate-options.rs:21:33
|
LL | options(att_syntax, noreturn),
| ^^^^^^^^ this option was already provided
error: the `nomem` option was already provided
--> $DIR/duplicate-options.rs:22:21
|
LL | options(nomem, nostack),
| ^^^^^ this option was already provided
error: the `noreturn` option was already provided
--> $DIR/duplicate-options.rs:23:21
|
LL | options(noreturn),
| ^^^^^^^^ this option was already provided
error: aborting due to 9 previous errors

View File

@ -34,11 +34,6 @@ fn main() {
//~^ ERROR expected one of
asm!("", options(nomem, foo));
//~^ ERROR expected one of
asm!("", options(), options());
//~^ ERROR asm options cannot be specified multiple times
asm!("", options(), options(), options());
//~^ ERROR asm options cannot be specified multiple times
//~^^ ERROR asm options cannot be specified multiple times
asm!("{}", options(), const foo);
//~^ ERROR arguments are not allowed after options
asm!("{a}", a = const foo, a = const bar);

View File

@ -82,32 +82,8 @@ error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `prese
LL | asm!("", options(nomem, foo));
| ^^^ expected one of 8 possible tokens
error: asm options cannot be specified multiple times
--> $DIR/parse-error.rs:37:29
|
LL | asm!("", options(), options());
| --------- ^^^^^^^^^ duplicate options
| |
| previously here
error: asm options cannot be specified multiple times
--> $DIR/parse-error.rs:39:29
|
LL | asm!("", options(), options(), options());
| --------- ^^^^^^^^^ duplicate options
| |
| previously here
error: asm options cannot be specified multiple times
--> $DIR/parse-error.rs:39:40
|
LL | asm!("", options(), options(), options());
| --------- ^^^^^^^^^ duplicate options
| |
| previously here
error: arguments are not allowed after options
--> $DIR/parse-error.rs:42:31
--> $DIR/parse-error.rs:37:31
|
LL | asm!("{}", options(), const foo);
| --------- ^^^^^^^^^ argument
@ -115,7 +91,7 @@ LL | asm!("{}", options(), const foo);
| previous options
error: duplicate argument named `a`
--> $DIR/parse-error.rs:44:36
--> $DIR/parse-error.rs:39:36
|
LL | asm!("{a}", a = const foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ duplicate argument
@ -123,7 +99,7 @@ LL | asm!("{a}", a = const foo, a = const bar);
| previously here
error: argument never used
--> $DIR/parse-error.rs:44:36
--> $DIR/parse-error.rs:39:36
|
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^^^^^^^^^^^ argument never used
@ -131,13 +107,13 @@ LL | asm!("{a}", a = const foo, a = const bar);
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
error: explicit register arguments cannot have names
--> $DIR/parse-error.rs:47:18
--> $DIR/parse-error.rs:42:18
|
LL | asm!("", a = in("eax") foo);
| ^^^^^^^^^^^^^^^^^
error: named arguments cannot follow explicit register arguments
--> $DIR/parse-error.rs:49:36
--> $DIR/parse-error.rs:44:36
|
LL | asm!("{a}", in("eax") foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ named argument
@ -145,7 +121,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| explicit register argument
error: named arguments cannot follow explicit register arguments
--> $DIR/parse-error.rs:51:36
--> $DIR/parse-error.rs:46:36
|
LL | asm!("{a}", in("eax") foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ named argument
@ -153,7 +129,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| explicit register argument
error: positional arguments cannot follow named arguments or explicit register arguments
--> $DIR/parse-error.rs:53:36
--> $DIR/parse-error.rs:48:36
|
LL | asm!("{1}", in("eax") foo, const bar);
| ------------- ^^^^^^^^^ positional argument
@ -161,19 +137,19 @@ LL | asm!("{1}", in("eax") foo, const bar);
| explicit register argument
error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
--> $DIR/parse-error.rs:55:29
--> $DIR/parse-error.rs:50:29
|
LL | asm!("", options(), "");
| ^^ expected one of 8 possible tokens
error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
--> $DIR/parse-error.rs:57:33
--> $DIR/parse-error.rs:52:33
|
LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
| ^^^^ expected one of 8 possible tokens
error: asm template must be a string literal
--> $DIR/parse-error.rs:59:14
--> $DIR/parse-error.rs:54:14
|
LL | asm!(format!("{{{}}}", 0), in(reg) foo);
| ^^^^^^^^^^^^^^^^^^^^
@ -181,12 +157,12 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo);
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: asm template must be a string literal
--> $DIR/parse-error.rs:61:21
--> $DIR/parse-error.rs:56:21
|
LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 28 previous errors
error: aborting due to 25 previous errors

View File

@ -0,0 +1,18 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
fn f(&self, x: &Self::U) {
<Self::U>::clone(x);
}
}
impl X<'_> for i32 {
type U = str;
//~^ ERROR the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone`
}
fn main() {
1i32.f("abc");
}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <i32 as X<'b>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-1.rs:12:14
|
LL | trait X<'a>
| - required by a bound in this
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<i32 as X<'b>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
fn f(&self, x: &Self::U) {
<Self::U>::clone(x);
}
}
impl X<'_> for u32
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U = str;
}
fn main() {
1u32.f("abc");
//~^ ERROR no method named `f` found for type `u32` in the current scope
}

View File

@ -0,0 +1,13 @@
error[E0599]: no method named `f` found for type `u32` in the current scope
--> $DIR/hr-associated-type-bound-2.rs:19:10
|
LL | 1u32.f("abc");
| ^ method not found in `u32`
|
= note: the method `f` exists but the following trait bounds were not satisfied:
`<u32 as X<'b>>::U: std::clone::Clone`
which is required by `u32: X`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View File

@ -0,0 +1,14 @@
trait X<'a>
where
for<'b> <Self as X<'b>>::U: Clone,
{
type U: ?Sized;
}
fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
//~^ ERROR the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
<<T as X<'_>>::U>::clone(x);
}
pub fn main() {
f::<dyn X<'_, U = str>>("abc");
}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <T as X<'b>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-object.rs:7:13
|
LL | trait X<'a>
| - required by a bound in this
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ----- required by this bound in `X`
...
LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) {
| ^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<T as X<'b>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
trait Y<'a, T: ?Sized>
where
T: Y<'a, Self>,
for<'b> <Self as Y<'b, T>>::V: Clone,
for<'b> <T as Y<'b, Self>>::V: Clone,
{
type V: ?Sized;
fn g(&self, x: &Self::V) {
<Self::V>::clone(x);
}
}
impl<'a> Y<'a, u8> for u8 {
type V = str;
//~^ ERROR the trait bound `for<'b> <u8 as Y<'b, u8>>::V: std::clone::Clone` is not satisfied
}
fn main() {
1u8.g("abc");
}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <u8 as Y<'b, u8>>::V: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-1.rs:14:14
|
LL | trait Y<'a, T: ?Sized>
| - required by a bound in this
...
LL | for<'b> <Self as Y<'b, T>>::V: Clone,
| ----- required by this bound in `Y`
...
LL | type V = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u8 as Y<'b, u8>>::V`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
trait Z<'a, T: ?Sized>
where
T: Z<'a, u16>,
//~^ the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
//~| the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
for<'b> <T as Z<'b, u16>>::W: Clone,
{
type W: ?Sized;
fn h(&self, x: &T::W) {
<T::W>::clone(x);
}
}
impl<'a> Z<'a, u16> for u16 {
type W = str;
//~^ ERROR the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone
}
fn main() {
1u16.h("abc");
}

View File

@ -0,0 +1,51 @@
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-2.rs:3:8
|
LL | trait Z<'a, T: ?Sized>
| - required by a bound in this
LL | where
LL | T: Z<'a, u16>,
| ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ----- required by this bound in `Z`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-2.rs:15:14
|
LL | trait Z<'a, T: ?Sized>
| - required by a bound in this
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ----- required by this bound in `Z`
...
LL | type W = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-2.rs:3:8
|
LL | trait Z<'a, T: ?Sized>
| - required by a bound in this
LL | where
LL | T: Z<'a, u16>,
| ^^^^^^^^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ----- required by this bound in `Z`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// ignore-tidy-linelength
trait X<'a, T>
where
for<'b> T: X<'b, T>,
for<'b> <T as X<'b, T>>::U: Clone,
{
type U: ?Sized;
fn f(x: &<T as X<'_, T>>::U) {
<<T as X<'_, T>>::U>::clone(x);
}
}
impl<S, T> X<'_, (T,)> for (S,) {
type U = str;
//~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied
}
pub fn main() {
<(i32,) as X<(i32,)>>::f("abc");
}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-3.rs:15:14
|
LL | trait X<'a, T>
| - required by a bound in this
...
LL | for<'b> <T as X<'b, T>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,19 @@
trait X<'a, T>
where
for<'b> (T,): X<'b, T>,
for<'b> <(T,) as X<'b, T>>::U: Clone,
{
type U: ?Sized;
fn f(x: &<(T,) as X<'_, T>>::U) {
<<(T,) as X<'_, T>>::U>::clone(x);
}
}
impl<S, T> X<'_, T> for (S,) {
type U = str;
//~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied
}
pub fn main() {
<(i32,) as X<i32>>::f("abc");
}

View File

@ -0,0 +1,19 @@
error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-4.rs:13:14
|
LL | trait X<'a, T>
| - required by a bound in this
...
LL | for<'b> <(T,) as X<'b, T>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<(T,) as X<'b, T>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,41 @@
// ignore-tidy-linelength
trait Cycle: Sized {
type Next: Cycle<Next = Self>;
}
impl<T> Cycle for Box<T> {
type Next = Vec<T>;
}
impl<T> Cycle for Vec<T> {
type Next = Box<T>;
}
trait X<'a, T: Cycle + for<'b> X<'b, T>>
where
for<'b> <T as X<'b, T>>::U: Clone,
for<'b> T::Next: X<'b, T::Next>,
for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
{
type U: ?Sized;
fn f(x: &<T as X<'_, T>>::U) {
<<T as X<'_, T>>::U>::clone(x);
}
}
impl<S, T> X<'_, Vec<T>> for S {
type U = str;
//~^ ERROR the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
//~| ERROR the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
}
impl<S, T> X<'_, Box<T>> for S {
type U = str;
//~^ ERROR the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
//~| ERROR the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
}
pub fn main() {
<i32 as X<Box<i32>>>::f("abc");
}

View File

@ -0,0 +1,67 @@
error[E0277]: the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-5.rs:28:14
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
| - required by a bound in this
...
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-5.rs:28:14
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
| - required by a bound in this
LL | where
LL | for<'b> <T as X<'b, T>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> <std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-5.rs:34:14
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
| - required by a bound in this
...
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::vec::Vec<T> as X<'b, std::vec::Vec<T>>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> <std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-5.rs:34:14
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
| - required by a bound in this
LL | where
LL | for<'b> <T as X<'b, T>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<std::boxed::Box<T> as X<'b, std::boxed::Box<T>>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,20 @@
trait X<'a, T>
where
for<'b> T: X<'b, T>,
for<'b> <T as X<'b, T>>::U: Clone,
{
type U: ?Sized;
fn f(x: &<T as X<'_, T>>::U) {
<<T as X<'_, T>>::U>::clone(x);
}
}
impl<S, T> X<'_, T> for (S,) {
//~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied
type U = str;
//~^ ERROR the trait bound `for<'b> <T as X<'b, T>>::U: std::clone::Clone` is not satisfied
}
pub fn main() {
<(i32,) as X<i32>>::f("abc");
}

View File

@ -0,0 +1,36 @@
error[E0277]: the trait bound `for<'b> <T as X<'b, T>>::U: std::clone::Clone` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:14:14
|
LL | trait X<'a, T>
| - required by a bound in this
...
LL | for<'b> <T as X<'b, T>>::U: Clone,
| ----- required by this bound in `X`
...
LL | type U = str;
| ^^^ the trait `for<'b> std::clone::Clone` is not implemented for `<T as X<'b, T>>::U`
|
= help: the following implementations were found:
<&T as std::clone::Clone>
<&mut T as std::clone::Clone>
error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied
--> $DIR/hr-associated-type-bound-param-6.rs:12:12
|
LL | trait X<'a, T>
| - required by a bound in this
LL | where
LL | for<'b> T: X<'b, T>,
| -------- required by this bound in `X`
...
LL | impl<S, T> X<'_, T> for (S,) {
| ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
trait UnsafeCopy<'a, T: Copy>
where
for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
{
type Item;
fn bug(item: &Self::Item) -> () {
let x: T = **item;
&x as *const _;
}
}
impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
//~^ ERROR the trait bound `<T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
type Item = T;
//~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref
}
pub fn main() {
<&'static str>::bug(&"");
}

View File

@ -0,0 +1,30 @@
error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
--> $DIR/hr-associated-type-projection-1.rs:15:17
|
LL | trait UnsafeCopy<'a, T: Copy>
| ---------- required by a bound in this
LL | where
LL | for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
| --------------------------- required by this bound in `UnsafeCopy`
...
LL | type Item = T;
| ^ the trait `for<'b> std::ops::Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
|
= help: the following implementations were found:
<&T as std::ops::Deref>
<&mut T as std::ops::Deref>
error[E0277]: the trait bound `<T as UnsafeCopy<'b, T>>::Item: std::ops::Deref` is not satisfied
--> $DIR/hr-associated-type-projection-1.rs:13:33
|
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
| ^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
|
help: consider further restricting the associated type
|
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where <T as UnsafeCopy<'b, T>>::Item: std::ops::Deref {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -3,11 +3,9 @@ use std::ops::Deref;
trait PointerFamily<U> {
type Pointer<T>: Deref<Target = T>;
//~^ ERROR generic associated types are unstable
//~| ERROR type-generic associated types are not yet implemented
type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
//~^ ERROR generic associated types are unstable
//~| ERROR where clauses on associated types are unstable
//~| ERROR type-generic associated types are not yet implemented
}
struct Foo;

View File

@ -8,7 +8,7 @@ LL | type Pointer<T>: Deref<Target = T>;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: generic associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:7:5
--> $DIR/feature-gate-generic_associated_types.rs:6:5
|
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: where clauses on associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:7:5
--> $DIR/feature-gate-generic_associated_types.rs:6:5
|
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -26,7 +26,7 @@ LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: generic associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:16:5
--> $DIR/feature-gate-generic_associated_types.rs:14:5
|
LL | type Pointer<Usize> = Box<Usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -35,7 +35,7 @@ LL | type Pointer<Usize> = Box<Usize>;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: generic associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:18:5
--> $DIR/feature-gate-generic_associated_types.rs:16:5
|
LL | type Pointer2<U32> = Box<U32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -44,7 +44,7 @@ LL | type Pointer2<U32> = Box<U32>;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: where clauses on associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:23:5
--> $DIR/feature-gate-generic_associated_types.rs:21:5
|
LL | type Assoc where Self: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -53,7 +53,7 @@ LL | type Assoc where Self: Sized;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: where clauses on associated types are unstable
--> $DIR/feature-gate-generic_associated_types.rs:28:5
--> $DIR/feature-gate-generic_associated_types.rs:26:5
|
LL | type Assoc where Self: Sized = Foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -61,22 +61,6 @@ LL | type Assoc where Self: Sized = Foo;
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error: type-generic associated types are not yet implemented
--> $DIR/feature-gate-generic_associated_types.rs:4:5
|
LL | type Pointer<T>: Deref<Target = T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: type-generic associated types are not yet implemented
--> $DIR/feature-gate-generic_associated_types.rs:7:5
|
LL | type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: aborting due to 9 previous errors
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,72 @@
#![allow(incomplete_features)]
#![feature(generic_associated_types)]
#![feature(associated_type_defaults)]
// A Collection trait and collection families. Based on
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
// associated-type-constructors-part-2-family-traits/
// check that we don't normalize with trait defaults.
trait Collection<T> {
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
fn empty() -> Self;
fn add(&mut self, value: T);
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
}
trait CollectionFamily {
type Member<T>: Collection<T, Family = Self>;
}
struct VecFamily;
impl CollectionFamily for VecFamily {
type Member<T> = Vec<T>;
}
impl<T> Collection<T> for Vec<T> {
type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
type Family = VecFamily;
fn empty() -> Self {
Vec::new()
}
fn add(&mut self, value: T) {
self.push(value)
}
fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
self.iter()
}
}
fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
where
C: Collection<i32>,
{
let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty();
for &v in ints.iterate() {
res.add(v as f32);
}
res
//~^ ERROR mismatched types
}
fn use_floatify() {
let a = vec![1i32, 2, 3];
let c = floatify_sibling(&a);
assert_eq!(Some(&1.0), c.iterate().next());
}
fn main() {
use_floatify();
}

View File

@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/collections-project-default.rs:60:5
|
LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
...
LL | res
| ^^^ expected Collection::Sibling, found CollectionFamily::Member
|
= note: expected associated type `<C as Collection<i32>>::Sibling<f32>`
found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@ -6,13 +6,14 @@
// http://smallcultfollowing.com/babysteps/blog/2016/11/03/
// associated-type-constructors-part-2-family-traits/
// run-pass
trait Collection<T> {
type Iter<'iter>: Iterator<Item=&'iter T>;
type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
<<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
//~^^ ERROR type-generic associated types are not yet implemented
fn empty() -> Self;
@ -23,7 +24,6 @@ trait Collection<T> {
trait CollectionFamily {
type Member<T>: Collection<T, Family = Self>;
//~^ ERROR type-generic associated types are not yet implemented
}
struct VecFamily;
@ -33,7 +33,7 @@ impl CollectionFamily for VecFamily {
}
impl<T> Collection<T> for Vec<T> {
type Iter<'iter> = std::slice::Iter<'iter, T>;
type Iter<'iter> where T: 'iter = std::slice::Iter<'iter, T>;
type Family = VecFamily;
fn empty() -> Self {
@ -53,18 +53,7 @@ fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>
where
C: Collection<i32>,
{
let mut res = C::Family::Member::<f32>::empty();
for &v in ints.iterate() {
res.add(v as f32);
}
res
}
fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
where
C: Collection<i32>,
{
let mut res = C::Family::Member::<f32>::empty();
let mut res = <C::Family as CollectionFamily>::Member::<f32>::empty();
for &v in ints.iterate() {
res.add(v as f32);
}
@ -72,11 +61,11 @@ where
}
fn use_floatify() {
let a = vec![1i32, 2, 3];
let b = floatify(a);
println!("{}", b.iterate().next());
let c = floatify_sibling(a);
println!("{}", c.iterate().next());
let a = vec![1, 2, 3];
let b = floatify(&a);
assert_eq!(Some(&1.0), b.iterate().next());
}
fn main() {}
fn main() {
use_floatify();
}

View File

@ -1,19 +0,0 @@
error: type-generic associated types are not yet implemented
--> $DIR/collections.rs:13:5
|
LL | / type Sibling<U>: Collection<U> =
LL | | <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
| |_________________________________________________________________________^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: type-generic associated types are not yet implemented
--> $DIR/collections.rs:25:5
|
LL | type Member<T>: Collection<T, Family = Self>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: aborting due to 2 previous errors

View File

@ -1,7 +1,7 @@
#![allow(incomplete_features)]
#![feature(generic_associated_types)]
// FIXME(#30472) normalize enough to handle this.
// check-pass
use std::ops::Deref;
@ -17,7 +17,6 @@ trait Baz {
}
impl<T> Baz for T where T: Foo {
//~^ ERROR type mismatch resolving
type Quux<'a> where T: 'a = T;
type Baa<'a> where T: 'a = &'a <T as Foo>::Bar<'a, 'static>;

View File

@ -1,18 +0,0 @@
error[E0271]: type mismatch resolving `for<'a> <<T as Baz>::Baa<'a> as std::ops::Deref>::Target == <<T as Baz>::Quux<'a> as Foo>::Bar<'a, 'static>`
--> $DIR/construct_with_other_type.rs:19:9
|
LL | impl<T> Baz for T where T: Foo {
| - ^^^ expected type parameter `T`, found associated type
| |
| this type parameter
|
= note: expected associated type `<T as Foo>::Bar<'_, 'static>`
found associated type `<<T as Baz>::Quux<'_> as Foo>::Bar<'_, 'static>`
help: consider further restricting this bound
|
LL | impl<T> Baz for T where T: Foo + Baz<Quux = T> {
| ^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.

View File

@ -6,7 +6,6 @@ struct Foo;
trait MyTrait {
type Item<T>;
//~^ ERROR generic associated types are unstable [E0658]
//~| ERROR type-generic associated types are not yet implemented
}
impl MyTrait for Foo {

View File

@ -8,7 +8,7 @@ LL | type Item<T>;
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error[E0658]: generic associated types are unstable
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:13:5
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:12:5
|
LL | type Item<T> = T;
| ^^^^^^^^^^^^^^^^^
@ -16,14 +16,6 @@ LL | type Item<T> = T;
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error: type-generic associated types are not yet implemented
--> $DIR/gat-dont-ice-on-absent-feature-2.rs:7:5
|
LL | type Item<T>;
| ^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -9,11 +9,8 @@ use std::fmt::{Display, Debug};
trait Foo {
type Assoc where Self: Sized;
type Assoc2<T> where T: Display;
//~^ ERROR type-generic associated types are not yet implemented
type Assoc3<T>;
//~^ ERROR type-generic associated types are not yet implemented
type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
//~^ ERROR type-generic associated types are not yet implemented
type WithDefault<'a, T: Debug + 'a>: ?Sized = dyn Iterator<Item=T>;
type NoGenerics;
}
@ -23,6 +20,7 @@ impl Foo for Bar {
type Assoc = usize;
type Assoc2<T> = Vec<T>;
type Assoc3<T> where T: Iterator = Vec<T>;
//~^ impl has stricter requirements than trait
type WithDefault<'a, T: Debug + 'a> = &'a dyn Iterator<Item=T>;
type NoGenerics = ::std::cell::Cell<i32>;
}

View File

@ -1,26 +1,12 @@
error: type-generic associated types are not yet implemented
--> $DIR/generic-associated-types-where.rs:11:5
|
LL | type Assoc2<T> where T: Display;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: type-generic associated types are not yet implemented
--> $DIR/generic-associated-types-where.rs:13:5
error[E0276]: impl has stricter requirements than trait
--> $DIR/generic-associated-types-where.rs:22:5
|
LL | type Assoc3<T>;
| ^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
| --------------- definition of `Assoc3` from trait
...
LL | type Assoc3<T> where T: Iterator = Vec<T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
error: type-generic associated types are not yet implemented
--> $DIR/generic-associated-types-where.rs:15:5
|
LL | type WithDefault<'a, T: Debug + 'a> = dyn Iterator<Item=T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: aborting due to 3 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0276`.

View File

@ -5,13 +5,13 @@
trait Foo {
type Assoc3<T>;
//~^ type-generic associated types are not yet implemented
}
struct Bar;
impl Foo for Bar {
type Assoc3<T> where T: Iterator = Vec<T>;
//~^ ERROR impl has stricter requirements than trait
}
fn main() {}

View File

@ -1,10 +1,12 @@
error: type-generic associated types are not yet implemented
--> $DIR/issue-47206-where-clause.rs:7:5
error[E0276]: impl has stricter requirements than trait
--> $DIR/issue-47206-where-clause.rs:13:5
|
LL | type Assoc3<T>;
| ^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
| --------------- definition of `Assoc3` from trait
...
LL | type Assoc3<T> where T: Iterator = Vec<T>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: std::iter::Iterator`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0276`.

View File

@ -1,11 +1,14 @@
#![allow(incomplete_features)]
#![feature(generic_associated_types)]
// FIXME(generic-associated-types) Investigate why this doesn't compile.
// check-pass
trait Iterator {
type Item<'a>: 'a;
//~^ ERROR the requirement `for<'a> <Self as Iterator>::Item<'a>: 'a` is not satisfied
}
impl Iterator for () {
type Item<'a> = &'a ();
}
fn main() {}

View File

@ -1,10 +0,0 @@
error[E0280]: the requirement `for<'a> <Self as Iterator>::Item<'a>: 'a` is not satisfied
--> $DIR/issue-62326-parameter-out-of-range.rs:7:20
|
LL | trait Iterator {
| -------- required by a bound in this
LL | type Item<'a>: 'a;
| ^^ required by this bound in `Iterator`
error: aborting due to previous error

View File

@ -7,7 +7,6 @@ trait Trait1 {
trait Trait2 {
type Type1<B>: Trait1<A=B>;
//~^ ERROR: generic associated types are unstable
//~| ERROR: type-generic associated types are not yet implemented
}
fn main() {}

View File

@ -7,14 +7,6 @@ LL | type Type1<B>: Trait1<A=B>;
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
= help: add `#![feature(generic_associated_types)]` to the crate attributes to enable
error: type-generic associated types are not yet implemented
--> $DIR/issue-67424.rs:8:5
|
LL | type Type1<B>: Trait1<A=B>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,32 @@
// Regression test for #68641
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait UnsafeCopy {
type Item<'a>: Copy;
fn copy<'a>(item: &Self::Item<'a>) -> Self::Item<'a> {
*item
}
}
impl<T> UnsafeCopy for T {
type Item<'a> = T;
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied
}
fn main() {
let mut s = String::from("Hello world!");
let copy = String::copy(&s);
// Do we indeed point to the samme memory?
assert!(s.as_ptr() == copy.as_ptr());
// Any use of `copy` is certeinly UB after this
drop(s);
// UB UB UB UB UB!!
println!("{}", copy);
}

View File

@ -0,0 +1,26 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68641-check-gat-bounds.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/issue-68641-check-gat-bounds.rs:15:5
|
LL | type Item<'a>: Copy;
| -------------------- required by `UnsafeCopy::Item`
...
LL | type Item<'a> = T;
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | impl<T: std::marker::Copy> UnsafeCopy for T {
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68642
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<fn() -> usize>::callme(|| 1);
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68642-broken-llvm-ir.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68642-broken-llvm-ir.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
| ------------------------ required by `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68643
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
pub fn main() {
<fn()>::callme(|| {});
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68643-broken-mir.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68643-broken-mir.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
| ------------------------ required by `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68644
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<u8>::callme(0);
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68644-codegen-selection.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68644-codegen-selection.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
| ------------------------ required by `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,21 @@
// Regression test for #68645
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait Fun {
type F<'a>: Fn() -> u32;
fn callme<'a>(f: Self::F<'a>) -> u32 {
f()
}
}
impl<T> Fun for T {
type F<'a> = Self;
//~^ ERROR expected a `std::ops::Fn<()>` closure, found `T`
}
fn main() {
<&dyn Iterator<Item = u8>>::callme(&std::iter::once(1));
}

View File

@ -0,0 +1,28 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68645-codegen-fulfillment.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0277]: expected a `std::ops::Fn<()>` closure, found `T`
--> $DIR/issue-68645-codegen-fulfillment.rs:15:5
|
LL | type F<'a>: Fn() -> u32;
| ------------------------ required by `Fun::F`
...
LL | type F<'a> = Self;
| ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
|
= help: the trait `std::ops::Fn<()>` is not implemented for `T`
= note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
help: consider restricting type parameter `T`
|
LL | impl<T: std::ops::Fn<()>> Fun for T {
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,22 @@
// Regression test for #68656
#![feature(generic_associated_types)]
//~^ WARNING the feature `generic_associated_types` is incomplete and may not
trait UnsafeCopy<T: Copy> {
type Item<'a>: std::ops::Deref<Target = T>;
fn bug<'a>(item: &Self::Item<'a>) -> () {
let x: T = **item;
&x as *const _;
}
}
impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
type Item<'a> = T;
//~^ ERROR type mismatch resolving `<T as std::ops::Deref>::Target == T`
}
fn main() {
<&'static str>::bug(&"");
}

View File

@ -0,0 +1,30 @@
warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-68656-unsized-values.rs:3:12
|
LL | #![feature(generic_associated_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
error[E0271]: type mismatch resolving `<T as std::ops::Deref>::Target == T`
--> $DIR/issue-68656-unsized-values.rs:16:5
|
LL | type Item<'a>: std::ops::Deref<Target = T>;
| ------------------------------------------- required by `UnsafeCopy::Item`
...
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<T> for T {
| - this type parameter
LL | type Item<'a> = T;
| ^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
|
= note: expected type parameter `T`
found associated type `<T as std::ops::Deref>::Target`
help: consider further restricting this bound
|
LL | impl<T: Copy + std::ops::Deref + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0271`.

View File

@ -1,7 +1,7 @@
#![allow(incomplete_features)]
#![feature(generic_associated_types)]
// FIXME(#30472) normalize enough to handle this.
// run-pass
trait Iterable {
type Item<'a> where Self: 'a;
@ -13,39 +13,35 @@ trait Iterable {
// Impl for struct type
impl<T> Iterable for Vec<T> {
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
//~^ ERROR type mismatch resolving
type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
fn iter<'a>(&'a self) -> Self::Iter<'a> {
//~^ ERROR type mismatch resolving
self.iter()
self[..].iter()
}
}
// Impl for a primitive type
impl<T> Iterable for [T] {
type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
//~^ ERROR type mismatch resolving
type Iter<'a> where T: 'a = std::slice::Iter<'a, T>;
fn iter<'a>(&'a self) -> Self::Iter<'a> {
//~^ ERROR type mismatch resolving
self.iter()
}
}
fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
fn make_iter<'a, I: Iterable + ?Sized>(it: &'a I) -> I::Iter<'a> {
it.iter()
}
fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
fn get_first<'a, I: Iterable + ?Sized>(it: &'a I) -> Option<I::Item<'a>> {
it.iter().next()
}
fn main() {
let v = vec![1, 2, 3];
assert_eq!(v, make_iter(&v).copied().collect());
assert_eq!(v, make_iter(&*v).copied().collect());
assert_eq!(1, get_first(&v));
assert_eq!(1, get_first(&*v));
assert_eq!(v, make_iter(&v).copied().collect::<Vec<_>>());
assert_eq!(v, make_iter(&*v).copied().collect::<Vec<_>>());
assert_eq!(Some(&1), get_first(&v));
assert_eq!(Some(&1), get_first(&*v));
}

View File

@ -1,59 +0,0 @@
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
--> $DIR/iterable.rs:15:33
|
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
= note: expected reference `&T`
found associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
= help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
--> $DIR/iterable.rs:27:33
|
LL | type Item<'a> where T: 'a = <std::slice::Iter<'a, T> as Iterator>::Item;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found associated type
|
= note: expected reference `&T`
found associated type `<[T] as Iterable>::Item<'_>`
= help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0271]: type mismatch resolving `for<'a> <<std::vec::Vec<T> as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <std::vec::Vec<T> as Iterable>::Item<'a>`
--> $DIR/iterable.rs:19:30
|
LL | trait Iterable {
| -------- required by a bound in this
LL | type Item<'a> where Self: 'a;
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
| --------------------- required by this bound in `Iterable`
...
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
| ^^^^^^^^^^^^^^ expected associated type, found reference
|
= note: expected associated type `<std::vec::Vec<T> as Iterable>::Item<'_>`
found reference `&T`
= help: consider constraining the associated type `<std::vec::Vec<T> as Iterable>::Item<'_>` to `&_` or calling a method that returns `<std::vec::Vec<T> as Iterable>::Item<'_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0271]: type mismatch resolving `for<'a> <<[T] as Iterable>::Iter<'a> as std::iter::Iterator>::Item == <[T] as Iterable>::Item<'a>`
--> $DIR/iterable.rs:31:30
|
LL | trait Iterable {
| -------- required by a bound in this
LL | type Item<'a> where Self: 'a;
LL | type Iter<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
| --------------------- required by this bound in `Iterable`
...
LL | fn iter<'a>(&'a self) -> Self::Iter<'a> {
| ^^^^^^^^^^^^^^ expected associated type, found reference
|
= note: expected associated type `<[T] as Iterable>::Item<'_>`
found reference `&T`
= help: consider constraining the associated type `<[T] as Iterable>::Item<'_>` to `&_` or calling a method that returns `<[T] as Iterable>::Item<'_>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0271`.

View File

@ -34,12 +34,11 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
struct E<B>(B);
impl<B: Add> Add for E<B> where B: Add<Output = B>, B: std::ops::Add<Output = B> {
//~^ ERROR equality constraints are not yet supported in `where` clauses
impl<B: Add> Add for E<B> where B: Add<Output = B> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0) //~ ERROR mismatched types
Self(self.0 + rhs.0)
}
}

Some files were not shown because too many files have changed in this diff Show More