Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd52230b

Browse files
dsymelatkin
authored andcommitted
skip unloadable interfaces
When the assembly reference set for the compilation is incomplete, somenterfaces to types relevant to compilation may lie in assemblies outsidethe assembly reference set. This applies particularly to private ("internalsvisible to") interfaces found in .NET assemblies.This causes very substantial usability bugs in practice as various parts oftype inference and other checking "give up" when you get this condition. TheC# compiler doesn't give up in the same way.In most cases it is reasonable to simply skip interfaces-that-lie-outside-the-set-of-referenced-assemblies during F# compilation. Skipping unresolvableinterfaces is pretty much harmless: any substantive analysis on the interfacetype (such as implementing it) will require the assembly holding the interfacetype.There are some exceptions: if an interface I1 lies outside the referenceableset and you try to implement I2 inheriting from I1 then we'd better not skipI1. Indeed if you even try to find the methods on I2 then we'd better not skipI1. These are covered by "FoldPrimaryHierarchyOfType" in the code.fixesdotnet#337closesdotnet#356commitdd5205cAuthor: Don Syme <donsyme@fastmail.fm>Date: Thu Apr 23 23:53:59 2015 +0100 add test casecommitdb28771Author: Don Syme <donsyme@fastmail.fm>Date: Fri Apr 10 12:18:50 2015 +0200 skip unloadable interfaces (2)commit18a4712Author: Don Syme <donsyme@fastmail.fm>Date: Fri Apr 10 11:53:39 2015 +0200 skip unloadable interfaces
1 parent90777db commitd52230b

File tree

8 files changed

+86
-21
lines changed

8 files changed

+86
-21
lines changed

‎src/fsharp/NicePrint.fs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,7 @@ module private TastDefinitionPrinting =
14191419
if suppressInheritanceAndInterfacesForTyInSimplifiedDisplays g amap m tythen
14201420
[]
14211421
else
1422-
GetImmediateInterfacesOfType g amap m ty|> List.map(fun ity-> wordL(if isInterfaceTy g tythen"inherit"else"interface")--- layoutType denv ity)
1422+
GetImmediateInterfacesOfTypeSkipUnrefInterfaces.Yesg amap m ty|> List.map(fun ity-> wordL(if isInterfaceTy g tythen"inherit"else"interface")--- layoutType denv ity)
14231423

14241424
letprops=
14251425
GetIntrinsicPropInfosOfType infoReader(None,ad,AllowMultiIntfInstantiations.Yes) PreferOverrides m ty

‎src/fsharp/check.fs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ let CheckEntityDefn cenv env (tycon:Entity) =
13691369
if cenv.reportErrorsthen
13701370
ifnot tycon.IsTypeAbbrevthen
13711371
lettyp= generalizedTyconRef(mkLocalTyconRef tycon)
1372-
letimmediateInterfaces= GetImmediateInterfacesOfType cenv.g cenv.amap m typ
1372+
letimmediateInterfaces= GetImmediateInterfacesOfTypeSkipUnrefInterfaces.Yescenv.g cenv.amap m typ
13731373
letinterfaces=
13741374
[for tyin immediateInterfacesdo
13751375
yield! AllSuperTypesOfType cenv.g cenv.amap m AllowMultiIntfInstantiations.Yes ty]

‎src/fsharp/import.fs‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ type ImportMap(g:TcGlobals,assemblyLoader:AssemblyLoader) =
6060
memberthis.assemblyLoader= assemblyLoader
6161
memberthis.ILTypeRefToTyconRefCache= typeRefToTyconRefCache
6262

63+
letCanImportILScopeRef(env:ImportMap)m scoref=
64+
match scorefwith
65+
| ILScopeRef.Local->true
66+
| ILScopeRef.Module_->true
67+
| ILScopeRef.Assembly assref->
68+
match env.assemblyLoader.LoadAssembly(m,assref)with
69+
| UnresolvedCcu_->false
70+
| ResolvedCcu_->true
71+
72+
6373
/// Import a reference to a type definition, given the AbstractIL data for the type reference
6474
letImportTypeRefData(env:ImportMap)m(scoref,path,typeName)=
6575
letccu=
@@ -123,6 +133,10 @@ let ImportILTypeRef (env:ImportMap) m (tref:ILTypeRef) =
123133
env.ILTypeRefToTyconRefCache.[tref]<- tcref
124134
tcref
125135

136+
/// Import a reference to a type definition, given an AbstractIL ILTypeRef, with caching
137+
letCanImportILTypeRef(env:ImportMap)m(tref:ILTypeRef)=
138+
env.ILTypeRefToTyconRefCache.ContainsKey(tref)|| CanImportILScopeRef env m tref.Scope
139+
126140
/// Import a type, given an AbstractIL ILTypeRef and an F# type instantiation.
127141
///
128142
/// Prefer the F# abbreviation for some built-in types, e.g. 'string' rather than
@@ -159,6 +173,19 @@ let rec ImportILType (env:ImportMap) m tinst typ =
159173
with_->
160174
error(Error(FSComp.SR.impNotEnoughTypeParamsInScopeWhileImporting(),m))
161175

176+
let recCanImportILType(env:ImportMap)m typ=
177+
match typwith
178+
| ILType.Void->true
179+
| ILType.Array(_bounds,ty)-> CanImportILType env m ty
180+
| ILType.Boxed tspec| ILType.Value tspec->
181+
CanImportILTypeRef env m tspec.TypeRef
182+
&& tspec.GenericArgs|> ILList.toList|> List.forall(CanImportILType env m)
183+
| ILType.Byref ty-> CanImportILType env m ty
184+
| ILType.Ptr ty-> CanImportILType env m ty
185+
| ILType.FunctionPointer_->true
186+
| ILType.Modified(_,_,ty)-> CanImportILType env m ty
187+
| ILType.TypeVar_u16->true
188+
162189
#if EXTENSIONTYPING
163190

164191
/// Import a provided type reference as an F# type TyconRef

‎src/fsharp/import.fsi‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,15 @@ type ImportMap =
4848
/// Import a reference to a type definition, given an AbstractIL ILTypeRef, with caching
4949
valinternalImportILTypeRef:ImportMap->range->ILTypeRef->TyconRef
5050

51+
/// Pre-check for ability to import a reference to a type definition, given an AbstractIL ILTypeRef, with caching
52+
valinternalCanImportILTypeRef:ImportMap->range->ILTypeRef->bool
53+
5154
/// Import an IL type as an F# type.
5255
valinternalImportILType:ImportMap->range->TType list->ILType->TType
5356

57+
/// Pre-check for ability to import an IL type as an F# type.
58+
valinternalCanImportILType:ImportMap->range->ILType->bool
59+
5460
#if EXTENSIONTYPING
5561

5662
/// Import a provided type as an F# type.

‎src/fsharp/infos.fs‎

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ open Microsoft.FSharp.Core.CompilerServices
3636
letImportType scoref amap m importInst ilty=
3737
ilty|> rescopeILType scoref|> Import.ImportILType amap m importInst
3838

39+
letCanImportType scoref amap m ilty=
40+
ilty|> rescopeILType scoref|> Import.CanImportILType amap m
41+
3942
//-------------------------------------------------------------------------
4043
// Fold the hierarchy.
4144
// REVIEW: this code generalizes the iteration used below for member lookup.
@@ -86,17 +89,21 @@ let GetSuperTypeOfType g amap m typ =
8689
/// Make a type for System.Collections.Generic.IList<ty>
8790
letmkSystemCollectionsGenericIListTy g ty= TType_app(g.tcref_System_Collections_Generic_IList,[ty])
8891

92+
[<RequireQualifiedAccess>]
93+
/// Indicates whether we can skip interface types that lie outside the reference set
94+
typeSkipUnrefInterfaces= Yes| No
95+
8996

9097
/// Collect the set of immediate declared interface types for an F# type, but do not
9198
/// traverse the type hierarchy to collect further interfaces.
92-
let recGetImmediateInterfacesOfType g amap m typ=
99+
let recGetImmediateInterfacesOfTypeskipUnrefg amap m typ=
93100
letitys=
94101
if isAppTy g typthen
95102
lettcref,tinst= destAppTy g typ
96103
if tcref.IsMeasureableReprTyconthen
97104
[match tcref.TypeReprInfowith
98105
| TMeasureableRepr reprTy->
99-
for ityin GetImmediateInterfacesOfType g amap m reprTydo
106+
for ityin GetImmediateInterfacesOfTypeskipUnrefg amap m reprTydo
100107
if isAppTy g itythen
101108
letitcref= tcrefOfAppTy g ity
102109
ifnot(tyconRefEq g itcref g.system_GenericIComparable_tcref)&&
@@ -113,7 +120,18 @@ let rec GetImmediateInterfacesOfType g amap m typ =
113120
yield Import.ImportProvidedType amap m ity]
114121
#endif
115122
| ILTypeMetadata(scoref,tdef)->
116-
tdef.Implements|> ILList.toList|> List.map(ImportType scoref amap m tinst)
123+
124+
// ImportType may fail for an interface if the assembly load set is incomplete and the interface
125+
// comes from another assembly. In this case we simply skip the interface:
126+
// if we don't skip it, then compilation will just fail here, and if type checking
127+
// succeeds with fewer non-dereferencable interfaces reported then it would have
128+
// succeeded with more reported. There are pathological corner cases where this
129+
// doesn't apply: e.g. for mscorlib interfaces like IComparable, but we can always
130+
// assume those are present.
131+
[for ityin tdef.Implements|> ILList.toListdo
132+
if skipUnref= SkipUnrefInterfaces.No|| CanImportType scoref amap m itythen
133+
yield ImportType scoref amap m tinst ity]
134+
117135
| FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata->
118136
tcref.ImmediateInterfaceTypesOfFSharpTycon|> List.map(instType(mkInstForAppTy g typ))
119137
else
@@ -133,7 +151,7 @@ type AllowMultiIntfInstantiations = Yes | No
133151

134152
/// Traverse the type hierarchy, e.g. f D (f C (f System.Object acc)).
135153
/// Visit base types and interfaces first.
136-
letprivateFoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst visitor g amap m typ acc=
154+
letprivateFoldHierarchyOfTypeAux followInterfaces allowMultiIntfInstskipUnrefvisitor g amap m typ acc=
137155
let recloop ndeep typ((visitedTycon,visited:TyconRefMultiMap<_>,acc)as state)=
138156

139157
letseenThisTycon= isAppTy g typ&& Set.contains(tcrefOfAppTy g typ).Stamp visitedTycon
@@ -157,7 +175,7 @@ let private FoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst visitor g
157175
if isInterfaceTy g typthen
158176
List.foldBack
159177
(loop(ndeep+1))
160-
(GetImmediateInterfacesOfType g amap m typ)
178+
(GetImmediateInterfacesOfTypeskipUnrefg amap m typ)
161179
(loop ndeep g.obj_ty state)
162180
elif isTyparTy g typthen
163181
lettp= destTyparTy g typ
@@ -186,7 +204,7 @@ let private FoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst visitor g
186204
if followInterfacesthen
187205
List.foldBack
188206
(loop(ndeep+1))
189-
(GetImmediateInterfacesOfType g amap m typ)
207+
(GetImmediateInterfacesOfTypeskipUnrefg amap m typ)
190208
state
191209
else
192210
state
@@ -200,22 +218,25 @@ let private FoldHierarchyOfTypeAux followInterfaces allowMultiIntfInst visitor g
200218
(visitedTycon,visited,acc)
201219
loop0 typ(Set.empty,TyconRefMultiMap<_>.Empty,acc)|> p33
202220

203-
/// Fold, do not follow interfaces
204-
letFoldPrimaryHierarchyOfType f g amap m allowMultiIntfInst typ acc= FoldHierarchyOfTypeAuxfalse allowMultiIntfInst f g amap m typ acc
221+
/// Fold, do not follow interfaces (unless the type is itself an interface)
222+
letFoldPrimaryHierarchyOfType f g amap m allowMultiIntfInst typ acc=
223+
FoldHierarchyOfTypeAuxfalse allowMultiIntfInst SkipUnrefInterfaces.No f g amap m typ acc
205224

206-
/// Fold, following interfaces
207-
letFoldEntireHierarchyOfType f g amap m allowMultiIntfInst typ acc= FoldHierarchyOfTypeAuxtrue allowMultiIntfInst f g amap m typ acc
225+
/// Fold, following interfaces. Skipping interfaces that lie outside the referenced assembly set is allowed.
226+
letFoldEntireHierarchyOfType f g amap m allowMultiIntfInst typ acc=
227+
FoldHierarchyOfTypeAuxtrue allowMultiIntfInst SkipUnrefInterfaces.Yes f g amap m typ acc
208228

209-
/// Iterate, following interfaces
210-
letIterateEntireHierarchyOfType f g amap m allowMultiIntfInst typ= FoldHierarchyOfTypeAuxtrue allowMultiIntfInst(fun ty()-> f ty) g amap m typ()
229+
/// Iterate, following interfaces. Skipping interfaces that lie outside the referenced assembly set is allowed.
230+
letIterateEntireHierarchyOfType f g amap m allowMultiIntfInst typ=
231+
FoldHierarchyOfTypeAuxtrue allowMultiIntfInst SkipUnrefInterfaces.Yes(fun ty()-> f ty) g amap m typ()
211232

212233
/// Search for one element satisfying a predicate, following interfaces
213234
letExistsInEntireHierarchyOfType f g amap m allowMultiIntfInst typ=
214-
FoldHierarchyOfTypeAuxtrue allowMultiIntfInst(fun ty acc-> acc|| f ty) g amap m typfalse
235+
FoldHierarchyOfTypeAuxtrue allowMultiIntfInstSkipUnrefInterfaces.Yes(fun ty acc-> acc|| f ty) g amap m typfalse
215236

216237
/// Search for one element where a function returns a 'Some' result, following interfaces
217238
letSearchEntireHierarchyOfType f g amap m typ=
218-
FoldHierarchyOfTypeAuxtrue AllowMultiIntfInstantiations.Yes
239+
FoldHierarchyOfTypeAuxtrue AllowMultiIntfInstantiations.Yes SkipUnrefInterfaces.Yes
219240
(fun ty acc->
220241
match accwith
221242
| None->if f tythen Some(ty)else None
@@ -224,7 +245,7 @@ let SearchEntireHierarchyOfType f g amap m typ =
224245

225246
/// Get all super types of the type, including the type itself
226247
letAllSuperTypesOfType g amap m allowMultiIntfInst ty=
227-
FoldHierarchyOfTypeAuxtrue allowMultiIntfInst(ListSet.insert(typeEquiv g)) g amap m ty[]
248+
FoldHierarchyOfTypeAuxtrue allowMultiIntfInstSkipUnrefInterfaces.No(ListSet.insert(typeEquiv g)) g amap m ty[]
228249

229250
/// Get all interfaces of a type, including the type itself if it is an interface
230251
letAllInterfacesOfType g amap m allowMultiIntfInst ty=

‎src/fsharp/typrelns.fs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ let rec TypeDefinitelySubsumesTypeNoCoercion ndeep g amap m ty1 ty2 =
7373
| Some ty-> TypeDefinitelySubsumesTypeNoCoercion(ndeep+1) g amap m ty1 ty)||
7474

7575
(isInterfaceTy g ty1&&
76-
ty2|> GetImmediateInterfacesOfType g amap m
76+
ty2|> GetImmediateInterfacesOfTypeSkipUnrefInterfaces.Yesg amap m
7777
|> List.exists(TypeDefinitelySubsumesTypeNoCoercion(ndeep+1) g amap m ty1))))
7878

7979

@@ -129,7 +129,7 @@ let rec TypeFeasiblySubsumesType ndeep g amap m ty1 canCoerce ty2 =
129129
| None->false
130130
| Some ty-> TypeFeasiblySubsumesType(ndeep+1) g amap m ty1 NoCoerce ty
131131
end||
132-
ty2|> GetImmediateInterfacesOfType g amap m
132+
ty2|> GetImmediateInterfacesOfTypeSkipUnrefInterfaces.Yesg amap m
133133
|> List.exists(TypeFeasiblySubsumesType(ndeep+1) g amap m ty1 NoCoerce))
134134

135135

@@ -1993,7 +1993,7 @@ let FinalTypeDefinitionChecksAtEndOfInferenceScope (infoReader:InfoReader) isImp
19931993
/// Look for the unique supertype of ty2 for which ty2 :> ty1 might feasibly hold
19941994
letFindUniqueFeasibleSupertype g amap m ty1 ty2=
19951995
ifnot(isAppTy g ty2)then Noneelse
1996-
letsupertypes= Option.toList(GetSuperTypeOfType g amap m ty2)@(GetImmediateInterfacesOfType g amap m ty2)
1996+
letsupertypes= Option.toList(GetSuperTypeOfType g amap m ty2)@(GetImmediateInterfacesOfTypeSkipUnrefInterfaces.Yesg amap m ty2)
19971997
supertypes|> List.tryFind(TypeFeasiblySubsumesType0 g amap m ty1 NoCoerce)
19981998

19991999

‎tests/fsharp/typecheck/sigs/build.bat‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ REM Configure the sample, i.e. where to find the F# compiler and C# compiler.
55

66
call%~d0%~p0..\..\..\config.bat
77

8+
"%FSC%" --noframework -r:"%FSCOREDLLPATH%" -r:"%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll" -r:"%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll" -r:"%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll" -r:"%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.dll" -r:"%X86_PROGRAMFILES%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Numerics.dll" -a -o:pos21.dll pos21.fs
9+
@if ERRORLEVEL1goto Error
10+
811
call ..\..\single-neg-test.bat neg91
912
@if ERRORLEVEL1goto Error
1013

@@ -517,7 +520,6 @@ call ..\..\single-neg-test.bat neg35
517520
"%FSC%"%fsc_flags% -a -o:pos05.dll pos05.fs
518521
@if ERRORLEVEL1goto Error
519522

520-
521523
:Ok
522524
echo Built fsharp%~f0 ok.
523525
endlocal
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespaceLibrary2
2+
3+
openSystem
4+
openSystem.Data
5+
6+
moduleM=
7+
letdataset=new DataSet("test add reference")
8+
Console.WriteLine(dataset.DataSetName)
9+
Console.ReadKey(true)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp