New type GenericArguments represents actual arguments to generics.

This commit is contained in:
Jason Orendorff 2022-05-07 15:18:59 -05:00 committed by Emilio Cobos Álvarez
parent 798cfab52b
commit 13c0a4a2e8
11 changed files with 242 additions and 93 deletions

View File

@ -5,7 +5,7 @@
use std::io::Write;
use crate::bindgen::declarationtyperesolver::DeclarationType;
use crate::bindgen::ir::{ArrayLength, Function, Type};
use crate::bindgen::ir::{ArrayLength, Function, GenericArgument, Type};
use crate::bindgen::writer::{ListType, SourceWriter};
use crate::bindgen::{Config, Language};
@ -35,7 +35,7 @@ impl CDeclarator {
struct CDecl {
type_qualifers: String,
type_name: String,
type_generic_args: Vec<Type>,
type_generic_args: Vec<GenericArgument>,
declarators: Vec<CDeclarator>,
type_ctype: Option<DeclarationType>,
}

View File

@ -10,8 +10,9 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, AnnotationValue, Cfg, ConditionWrite, Documentation, Field, GenericParams,
GenericPath, Item, ItemContainer, Literal, Path, Repr, ReprStyle, Struct, ToCondition, Type,
AnnotationSet, AnnotationValue, Cfg, ConditionWrite, Documentation, Field, GenericArgument,
GenericParams, GenericPath, Item, ItemContainer, Literal, Path, Repr, ReprStyle, Struct,
ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@ -61,8 +62,8 @@ impl VariantBody {
fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
generic_values: &[GenericArgument],
mappings: &[(&Path, &GenericArgument)],
config: &Config,
) -> Self {
match *self {
@ -265,8 +266,8 @@ impl EnumVariant {
fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
generic_values: &[GenericArgument],
mappings: &[(&Path, &GenericArgument)],
config: &Config,
) -> Self {
Self::new(
@ -611,7 +612,7 @@ impl Item for Enum {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
generic_values: &[GenericArgument],
library: &Library,
out: &mut Monomorphs,
) {

View File

@ -5,7 +5,7 @@ use syn::ext::IdentExt;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::{DeclarationType, DeclarationTypeResolver};
use crate::bindgen::ir::{Path, Type};
use crate::bindgen::ir::{ArrayLength, Path, Type};
use crate::bindgen::utilities::IterHelpers;
use crate::bindgen::writer::{Source, SourceWriter};
@ -19,7 +19,8 @@ impl GenericParams {
.params
.iter()
.filter_map(|x| match *x {
syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => {
syn::GenericParam::Type(syn::TypeParam { ref ident, .. })
| syn::GenericParam::Const(syn::ConstParam { ref ident, .. }) => {
Some(Path::new(ident.unraw().to_string()))
}
_ => None,
@ -69,16 +70,52 @@ impl Source for GenericParams {
}
}
/// A (non-lifetime) argument passed to a generic, either a type or a constant expression.
///
/// Note: Both arguments in a type like `Array<T, N>` are represented as
/// `GenericArgument::Type`s, even if `N` is actually the name of a const. This
/// is a consequence of `syn::GenericArgument` doing the same thing.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum GenericArgument {
Type(Type),
Const(ArrayLength),
}
impl GenericArgument {
pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> GenericArgument {
match *self {
GenericArgument::Type(ref ty) => GenericArgument::Type(ty.specialize(mappings)),
GenericArgument::Const(ref expr) => GenericArgument::Const(expr.clone()),
}
}
pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
match *self {
GenericArgument::Type(ref mut ty) => ty.rename_for_config(config, generic_params),
GenericArgument::Const(ref mut expr) => expr.rename_for_config(config),
}
}
}
impl Source for GenericArgument {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
match *self {
GenericArgument::Type(ref ty) => ty.write(config, out),
GenericArgument::Const(ref expr) => expr.write(config, out),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GenericPath {
path: Path,
export_name: String,
generics: Vec<Type>,
generics: Vec<GenericArgument>,
ctype: Option<DeclarationType>,
}
impl GenericPath {
pub fn new(path: Path, generics: Vec<Type>) -> Self {
pub fn new(path: Path, generics: Vec<GenericArgument>) -> Self {
let export_name = path.name().to_owned();
Self {
path,
@ -103,11 +140,11 @@ impl GenericPath {
&self.path
}
pub fn generics(&self) -> &[Type] {
pub fn generics(&self) -> &[GenericArgument] {
&self.generics
}
pub fn generics_mut(&mut self) -> &mut [Type] {
pub fn generics_mut(&mut self) -> &mut [GenericArgument] {
&mut self.generics
}
@ -123,6 +160,10 @@ impl GenericPath {
&self.export_name
}
pub fn is_single_identifier(&self) -> bool {
self.generics.is_empty()
}
pub fn rename_for_config(&mut self, config: &Config, generic_params: &GenericParams) {
for generic in &mut self.generics {
generic.rename_for_config(config, generic_params);
@ -156,8 +197,11 @@ impl GenericPath {
ref args,
..
}) => args.iter().try_skip_map(|x| match *x {
syn::GenericArgument::Type(ref x) => Type::load(x),
syn::GenericArgument::Type(ref x) => Ok(Type::load(x)?.map(GenericArgument::Type)),
syn::GenericArgument::Lifetime(_) => Ok(None),
syn::GenericArgument::Const(ref x) => {
Ok(Some(GenericArgument::Const(ArrayLength::load(x)?)))
}
_ => Err(format!("can't handle generic argument {:?}", x)),
})?,
syn::PathArguments::Parenthesized(_) => {

View File

@ -9,7 +9,8 @@ use crate::bindgen::config::Config;
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, Constant, Enum, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
AnnotationSet, Cfg, Constant, Enum, GenericArgument, OpaqueItem, Path, Static, Struct, Typedef,
Union,
};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
@ -37,7 +38,12 @@ pub trait Item {
}
fn rename_for_config(&mut self, _config: &Config) {}
fn add_dependencies(&self, _library: &Library, _out: &mut Dependencies) {}
fn instantiate_monomorph(&self, _generics: &[Type], _library: &Library, _out: &mut Monomorphs) {
fn instantiate_monomorph(
&self,
_generics: &[GenericArgument],
_library: &Library,
_out: &mut Monomorphs,
) {
unreachable!("Cannot instantiate {} as a generic.", self.name())
}
}

View File

@ -8,8 +8,8 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
ToCondition, Type,
AnnotationSet, Cfg, ConditionWrite, Documentation, GenericArgument, GenericParams, Item,
ItemContainer, Path, ToCondition,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@ -98,7 +98,7 @@ impl Item for OpaqueItem {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
generic_values: &[GenericArgument],
library: &Library,
out: &mut Monomorphs,
) {

View File

@ -10,8 +10,9 @@ use crate::bindgen::config::{Config, Language, LayoutConfig};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, Field, GenericParams, Item,
ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type, Typedef,
AnnotationSet, Cfg, ConditionWrite, Constant, Documentation, Field, GenericArgument,
GenericParams, Item, ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition, Type,
Typedef,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@ -174,8 +175,8 @@ impl Struct {
pub fn specialize(
&self,
generic_values: &[Type],
mappings: &[(&Path, &Type)],
generic_values: &[GenericArgument],
mappings: &[(&Path, &GenericArgument)],
config: &Config,
) -> Self {
let mangled_path = mangle::mangle_path(&self.path, generic_values, &config.export.mangle);
@ -365,7 +366,7 @@ impl Item for Struct {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
generic_values: &[GenericArgument],
library: &Library,
out: &mut Monomorphs,
) {

View File

@ -11,7 +11,7 @@ use crate::bindgen::cdecl;
use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{GenericParams, GenericPath, Path};
use crate::bindgen::ir::{GenericArgument, GenericParams, GenericPath, Path};
use crate::bindgen::library::Library;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::utilities::IterHelpers;
@ -320,16 +320,64 @@ pub enum ArrayLength {
impl ArrayLength {
pub fn as_str(&self) -> &str {
match self {
match *self {
ArrayLength::Name(ref string) | ArrayLength::Value(ref string) => string,
}
}
fn rename_for_config(&mut self, config: &Config) {
pub fn rename_for_config(&mut self, config: &Config) {
if let ArrayLength::Name(ref mut name) = self {
config.export.rename(name);
}
}
pub fn load(expr: &syn::Expr) -> Result<Self, String> {
match *expr {
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Int(ref len),
..
}) => Ok(ArrayLength::Value(len.base10_digits().to_string())),
syn::Expr::Path(ref path) => {
let generic_path = GenericPath::load(&path.path)?;
Ok(ArrayLength::Name(generic_path.export_name().to_owned()))
}
_ => Err(format!("can't handle const expression {:?}", expr)),
}
}
pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> ArrayLength {
match *self {
ArrayLength::Name(ref name) => {
let path = Path::new(name);
for &(param, value) in mappings {
if path == *param {
match *value {
GenericArgument::Type(Type::Path(ref path))
if path.is_single_identifier() =>
{
// This happens when the generic argument is a path.
return ArrayLength::Name(path.name().to_string());
}
GenericArgument::Const(ref expr) => {
return expr.clone();
}
_ => {
// unsupported argument type - really should be an error
}
}
}
}
}
ArrayLength::Value(_) => {}
}
self.clone()
}
}
impl Source for ArrayLength {
fn write<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) {
write!(out, "{}", self.as_str());
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
@ -415,28 +463,7 @@ impl Type {
}
}
syn::Type::Array(syn::TypeArray {
ref elem,
len: syn::Expr::Path(ref path),
..
}) => {
let converted = Type::load(elem)?;
let converted = match converted {
Some(converted) => converted,
None => return Err("Cannot have an array of zero sized types.".to_owned()),
};
let generic_path = GenericPath::load(&path.path)?;
let len = ArrayLength::Name(generic_path.export_name().to_owned());
Type::Array(Box::new(converted), len)
}
syn::Type::Array(syn::TypeArray {
ref elem,
len:
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Int(ref len),
..
}),
..
ref elem, ref len, ..
}) => {
let converted = Type::load(elem)?;
@ -445,8 +472,7 @@ impl Type {
None => return Err("Cannot have an array of zero sized types.".to_owned()),
};
let len = ArrayLength::Value(len.base10_digits().to_string());
// panic!("panic -> value: {:?}", len);
let len = ArrayLength::load(len)?;
Type::Array(Box::new(converted), len)
}
syn::Type::BareFn(ref function) => {
@ -609,7 +635,11 @@ impl Type {
return None;
}
let unsimplified_generic = &path.generics()[0];
let unsimplified_generic = match path.generics()[0] {
GenericArgument::Type(ref ty) => ty,
GenericArgument::Const(_) => return None,
};
let generic = match unsimplified_generic.simplified_type(config) {
Some(generic) => Cow::Owned(generic),
None => Cow::Borrowed(unsimplified_generic),
@ -663,7 +693,10 @@ impl Type {
Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty),
Type::Path(ref mut path) => {
for generic in path.generics_mut() {
visitor(generic);
match *generic {
GenericArgument::Type(ref mut ty) => visitor(ty),
GenericArgument::Const(_) => {}
}
}
}
Type::Primitive(..) => {}
@ -701,7 +734,7 @@ impl Type {
}
}
pub fn specialize(&self, mappings: &[(&Path, &Type)]) -> Type {
pub fn specialize(&self, mappings: &[(&Path, &GenericArgument)]) -> Type {
match *self {
Type::Ptr {
ref ty,
@ -717,7 +750,9 @@ impl Type {
Type::Path(ref generic_path) => {
for &(param, value) in mappings {
if generic_path.path() == param {
return value.clone();
if let GenericArgument::Type(ref ty) = *value {
return ty.clone();
}
}
}
@ -732,9 +767,10 @@ impl Type {
Type::Path(specialized)
}
Type::Primitive(ref primitive) => Type::Primitive(primitive.clone()),
Type::Array(ref ty, ref constant) => {
Type::Array(Box::new(ty.specialize(mappings)), constant.clone())
}
Type::Array(ref ty, ref constant) => Type::Array(
Box::new(ty.specialize(mappings)),
constant.specialize(mappings),
),
Type::FuncPtr {
ref ret,
ref args,
@ -763,7 +799,9 @@ impl Type {
}
Type::Path(ref generic) => {
for generic_value in generic.generics() {
generic_value.add_dependencies_ignoring_generics(generic_params, library, out);
if let GenericArgument::Type(ref ty) = *generic_value {
ty.add_dependencies_ignoring_generics(generic_params, library, out);
}
}
let path = generic.path();
if !generic_params.contains(path) {

View File

@ -11,8 +11,8 @@ use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer,
Path, ToCondition, Type,
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericArgument, GenericParams, Item,
ItemContainer, Path, ToCondition, Type,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@ -155,7 +155,7 @@ impl Item for Typedef {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
generic_values: &[GenericArgument],
library: &Library,
out: &mut Monomorphs,
) {

View File

@ -10,8 +10,8 @@ use crate::bindgen::config::{Config, Language, LayoutConfig};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericParams, Item, ItemContainer,
Path, Repr, ReprAlign, ReprStyle, ToCondition, Type,
AnnotationSet, Cfg, ConditionWrite, Documentation, Field, GenericArgument, GenericParams, Item,
ItemContainer, Path, Repr, ReprAlign, ReprStyle, ToCondition,
};
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
@ -223,7 +223,7 @@ impl Item for Union {
fn instantiate_monomorph(
&self,
generic_values: &[Type],
generic_values: &[GenericArgument],
library: &Library,
out: &mut Monomorphs,
) {

View File

@ -3,14 +3,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::bindgen::config::MangleConfig;
use crate::bindgen::ir::{Path, Type};
use crate::bindgen::ir::{ArrayLength, GenericArgument, GenericPath, Path, Type};
use crate::bindgen::rename::IdentifierType;
pub fn mangle_path(path: &Path, generic_values: &[Type], config: &MangleConfig) -> Path {
pub fn mangle_path(path: &Path, generic_values: &[GenericArgument], config: &MangleConfig) -> Path {
Path::new(mangle_name(path.name(), generic_values, config))
}
pub fn mangle_name(name: &str, generic_values: &[Type], config: &MangleConfig) -> String {
pub fn mangle_name(
name: &str,
generic_values: &[GenericArgument],
config: &MangleConfig,
) -> String {
Mangler::new(name, generic_values, /* last = */ true, config).mangle()
}
@ -27,7 +31,7 @@ enum Separator {
struct Mangler<'a> {
input: &'a str,
generic_values: &'a [Type],
generic_values: &'a [GenericArgument],
output: String,
last: bool,
config: &'a MangleConfig,
@ -36,7 +40,7 @@ struct Mangler<'a> {
impl<'a> Mangler<'a> {
fn new(
input: &'a str,
generic_values: &'a [Type],
generic_values: &'a [GenericArgument],
last: bool,
config: &'a MangleConfig,
) -> Self {
@ -64,6 +68,20 @@ impl<'a> Mangler<'a> {
self.output.extend(std::iter::repeat(separator).take(count));
}
fn append_mangled_argument(&mut self, arg: &GenericArgument, last: bool) {
match *arg {
GenericArgument::Type(ref ty) => self.append_mangled_type(ty, last),
GenericArgument::Const(ArrayLength::Name(ref name)) => {
// This must behave the same as a GenericArgument::Type,
// because const arguments are commonly represented as Types;
// see the comment on `enum GenericArgument`.
let fake_ty = Type::Path(GenericPath::new(Path::new(name), vec![]));
self.append_mangled_type(&fake_ty, last);
}
GenericArgument::Const(ArrayLength::Value(ref val)) => self.output.push_str(val),
}
}
fn append_mangled_type(&mut self, ty: &Type, last: bool) {
match *ty {
Type::Path(ref generic) => {
@ -128,12 +146,12 @@ impl<'a> Mangler<'a> {
}
self.push(Separator::OpeningAngleBracket);
for (i, ty) in self.generic_values.iter().enumerate() {
for (i, arg) in self.generic_values.iter().enumerate() {
if i != 0 {
self.push(Separator::Comma);
}
let last = self.last && i == self.generic_values.len() - 1;
self.append_mangled_type(ty, last);
self.append_mangled_argument(arg, last);
}
// Skip writing the trailing '>' mangling when possible
@ -148,22 +166,22 @@ fn generics() {
use crate::bindgen::ir::{GenericPath, PrimitiveType};
use crate::bindgen::rename::RenameRule::{self, PascalCase};
fn float() -> Type {
Type::Primitive(PrimitiveType::Float)
fn float() -> GenericArgument {
GenericArgument::Type(Type::Primitive(PrimitiveType::Float))
}
fn c_char() -> Type {
Type::Primitive(PrimitiveType::Char)
fn c_char() -> GenericArgument {
GenericArgument::Type(Type::Primitive(PrimitiveType::Char))
}
fn path(path: &str) -> Type {
fn path(path: &str) -> GenericArgument {
generic_path(path, &[])
}
fn generic_path(path: &str, generics: &[Type]) -> Type {
fn generic_path(path: &str, arguments: &[GenericArgument]) -> GenericArgument {
let path = Path::new(path);
let generic_path = GenericPath::new(path, generics.to_owned());
Type::Path(generic_path)
let generic_path = GenericPath::new(path, arguments.to_owned());
GenericArgument::Type(Type::Path(generic_path))
}
// Foo<f32> => Foo_f32
@ -288,4 +306,43 @@ fn generics() {
),
Path::new("FooBarTBarE")
);
assert_eq!(
mangle_path(
&Path::new("Top"),
&[GenericArgument::Const(ArrayLength::Value("40".to_string()))],
&MangleConfig::default(),
),
Path::new("Top_40")
);
assert_eq!(
mangle_path(
&Path::new("Top"),
&[GenericArgument::Const(ArrayLength::Name("N".to_string()))],
&MangleConfig::default(),
),
Path::new("Top_N")
);
assert_eq!(
mangle_path(
&Path::new("Top"),
&[generic_path("N", &[])],
&MangleConfig::default(),
),
Path::new("Top_N")
);
assert_eq!(
mangle_path(
&Path::new("Foo"),
&[
float(),
GenericArgument::Const(ArrayLength::Value("40".to_string()))
],
&MangleConfig::default(),
),
Path::new("Foo_f32__40")
);
}

View File

@ -5,7 +5,9 @@
use std::collections::HashMap;
use std::mem;
use crate::bindgen::ir::{Enum, GenericPath, OpaqueItem, Path, Struct, Type, Typedef, Union};
use crate::bindgen::ir::{
Enum, GenericArgument, GenericPath, OpaqueItem, Path, Struct, Typedef, Union,
};
use crate::bindgen::library::Library;
#[derive(Default, Clone, Debug)]
@ -28,9 +30,9 @@ impl Monomorphs {
library: &Library,
generic: &Struct,
monomorph: Struct,
parameters: Vec<Type>,
arguments: Vec<GenericArgument>,
) {
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
let replacement_path = GenericPath::new(generic.path.clone(), arguments);
debug_assert!(generic.generic_params.len() > 0);
debug_assert!(!self.contains(&replacement_path));
@ -48,9 +50,9 @@ impl Monomorphs {
library: &Library,
generic: &Enum,
monomorph: Enum,
parameters: Vec<Type>,
arguments: Vec<GenericArgument>,
) {
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
let replacement_path = GenericPath::new(generic.path.clone(), arguments);
debug_assert!(generic.generic_params.len() > 0);
debug_assert!(!self.contains(&replacement_path));
@ -68,9 +70,9 @@ impl Monomorphs {
library: &Library,
generic: &Union,
monomorph: Union,
parameters: Vec<Type>,
arguments: Vec<GenericArgument>,
) {
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
let replacement_path = GenericPath::new(generic.path.clone(), arguments);
debug_assert!(generic.generic_params.len() > 0);
debug_assert!(!self.contains(&replacement_path));
@ -87,9 +89,9 @@ impl Monomorphs {
&mut self,
generic: &OpaqueItem,
monomorph: OpaqueItem,
parameters: Vec<Type>,
arguments: Vec<GenericArgument>,
) {
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
let replacement_path = GenericPath::new(generic.path.clone(), arguments);
debug_assert!(generic.generic_params.len() > 0);
debug_assert!(!self.contains(&replacement_path));
@ -104,9 +106,9 @@ impl Monomorphs {
library: &Library,
generic: &Typedef,
monomorph: Typedef,
parameters: Vec<Type>,
arguments: Vec<GenericArgument>,
) {
let replacement_path = GenericPath::new(generic.path.clone(), parameters);
let replacement_path = GenericPath::new(generic.path.clone(), arguments);
debug_assert!(generic.generic_params.len() > 0);
debug_assert!(!self.contains(&replacement_path));